Store
Community Documentation

v3 Knowledgebase

Marketplace Messages to Lister

I read in one of the forum post about the desire to have a marketplace user be able to send a message to the listing owner based upon the privacy settings that the owner had set in the listing comment privacy setting. This seems to be a reasonable request. The listing owner should be able to choose to open the listing up for messages and many times people want to ask questions that do not need to be public in nature.

Unfortunately, Phpfox has many checks to shield users from unwanted messages and finding a way to provide exceptions to these checks can be daunting.

I started out by following the code stream from the ‘Send a message’ button on the listing. It calls some jQuery code which in turn opens a box and, through the mail ajax file, loads the mail compose controller. Then, upon submitting the form, the message is created normally through the controller and the mail.process->add() function.

Armed with this information, I started looking for hooks that might provide a good base for changing the requirements. I found that, within the compose component was a call to a mail.service-canMessageUser() function. This checks the various settings to determine if the mail can be sent according to the rules set up within phpfox. This has a hook at the beginning and a neat feature that allows you to set a variable within the plugin that will make it skip the rest of the function. So all I need to do is perform my own checks and set the $bCanOverrideChecks to true and I can allow the message to be sent. At least that was how I thought it would work.

Since most of the checks are good ones, like do not allow blocked members to message the blocker, I needed to keep them in place. I copied the existing function checks into my plugin and then changed them so they would work properly within their new environment. (Returns do not always do what you want inside a plugin.) My theory was that I could find the check that looks at the privacy settings and change it to use the listing comment privacy setting instead of the user privacy setting.
PHP:
// This plugin will cause certain mail requests from marketplace 'Contact Seller'
// to skip the normal privacy checks.  It uses a modified copy of the privacy
// checks to determine if the mail can be sent.
// These are the cases where the mail will not be sent:
// 1. If the user group settings do not allow the current user to send mail messages.
// 2. If the current user cannot comment on the listing.
// 3. If the current user has been blocked.
// 4. If the message is to the current user themself and their usergroup setting does not allow this.

// It must also have the modified block marketplace.newprice installed replacing marketplace.price
// And the accompanying plugin mail.service_process_add.

if($this->request()->get('source')=='marketplace')
{
    
//Start sessionvars at none
    
Phpfox::getLib('session')->remove('RemoveFriend');
    
Phpfox::getLib('session')->remove('MailSource');
    
Phpfox::getLib('session')->remove('OriginalUserPrivacy');

//echo 'First time';
    
$iUserId =   $this->request()->get('id');
    
$bIsFriend=Phpfox::getService('friend')->isFriend(Phpfox::getUserId(), $iUserId)?true:false;
    
$sModule =   $this->request()->get('source');
    
$iItemId =   $this->request()->get('listing_id');
    
$iPrivacy $this->database()->select('privacy_comment')
            ->
from(Phpfox::getT('marketplace'))
            ->
where('listing_id = ' . (int) $iItemId)
            ->
execute('getSlaveField');
    
$iPrivacyUser $this->database()->select('user_value')
            ->
from(Phpfox::getT('user_privacy'))
            ->
where('user_privacy = "mail.send_message" AND user_id = ' . (int) $iUserId)
            ->
execute('getSlaveField');

    
// Set a pass/fail var.  If any step causes a false, the message will not be sent.
    
$bTestOk=true;

    
// 1. Do we need to do anything?
    
if (!empty($iPrivacyUser))
    {
        if (
$iPrivacyUser == && $iPrivacy == 3// No one
        
{
            
//keep existing system
            
$bTestOk=false;
        }
        else if (
$iPrivacyUser == && $iPrivacy == 1// friends only
        
{                
            
//keep existing system
            
$bTestOk=false;
        }
        else
        {
            
//Temp change lister's user privacy
            
$bChangeUserPrivacy=true;
            
$bTestOk=true;
        }
    }

    
// 2. Does user group settings disallowthis?
    
if ($bTestOk===true && !Phpfox::getUserParam('mail.can_compose_message'))
    {    
        
$bTestOk=false;
    }

    
// 3. Does Listing Comment Privacy setting allow a message for this viewer?
    
if ($bTestOk===true && Phpfox::isModule('privacy')) 
    {
        
$bTestOk Phpfox::getService('privacy')->check($sModule$iItemId$iUserId$iPrivacy$bIsFriend,true);
    }


    
// 4. Has lister blocked this viewer?
    
if ($bTestOk===true && !Phpfox::isAdmin() && (Phpfox::getService('user.block')->isBlocked(Phpfox::getUserId(), $iUser) > || Phpfox::getService('user.block')->isBlocked($iUserPhpfox::getUserId()) > 0))
    {    
        
$bTestOk=false;
    }

    
// 5. If sending message to oneself, does the setting mail.can_message_self allow this?
    
if ($bTestOk===true && $iUser == Phpfox::getUserId() && !Phpfox::getUserParam('mail.can_message_self'))
    {    
        
$bTestOk=false;
    }

    
// if $bTestOk is true then skip normal tests
    
if($bTestOk===true)
    {
        
// This var will skip the normal checks in this function
        
$bCanOverrideChecks=true;

        
//We need to set a session var so we know the request is from marketplace on pass 2
        
Phpfox::getLib('session')->set('MailSource''marketplace');

        
//We need to set a session var so we know to remove the temp friend later.
        
if(!$bIsFriend)
        {
            
Phpfox::getLib('session')->set('RemoveFriend'True);
        }

        
//We need to set a parameter to restore user privacy setting.
        
if($bChangeUserPrivacy)
        {
            
Phpfox::getLib('session')->set('OriginalUserPrivacy'$iPrivacyUser);
        }
    }
}

// If there is no request with a marketplace parameter but there is a marketplace session var
// Then it indicates the second pass where the message is being sent.
elseif(Phpfox::getLib('session')->get('MailSource')=='marketplace')
{
    
$aVals $this->request()->getArray('val');
    
$iUserId=$aVals['to'][ ];
    if(
Phpfox::getLib('session')->get('OriginalUserPrivacy')>0)
    {
        
Phpfox::getLib('database')->update(Phpfox::getT('user_privacy'), array('user_value' => (int)1), 'user_id = ' $iUserId ' AND user_privacy = "mail.send_message"' );
    }

    
//Temporarily set friends table
    //This will be removed by plugin 'mail.service_process_add'


    
if(Phpfox::getLib('session')->get('RemoveFriend'))
    {
        
// Add friends
        
$this->database()->insert(Phpfox::getT('friend'), array(
            
'list_id' => 0,
            
'user_id' => $iUserId,
            
'friend_user_id' => Phpfox::getUserId(),
            
'time_stamp' => PHPFOX_TIME
            
)
        );
        
$this->database()->insert(Phpfox::getT('friend'), array(
            
'list_id' => 0,
            
'user_id' => Phpfox::getUserId(),
            
'friend_user_id' => $iUserId,
            
'time_stamp' => PHPFOX_TIME
            
)
        );
    }


    
// We don't need the normal checks on the second pass either
    
$bCanOverrideChecks=true;
    
// We no longer need this session var
    
Phpfox::getLib('session')->remove('MailSource');


To find the code to check the listing privacy, I found in the privacy.service a check function. If given the proper passed variables, it will return a true or false response reflecting whether the privacy settings will allow the action to occur. This was what I needed, but it requires more information than the form normally sends. The form that contains the Send message button has all of that info, but I need to get it to the plugin somehow. I would need to add parameters to the initial request to transfer the information. But the submit button calls a jQuery function to do this. There is no good way that I could see to do this, especially since this seems to be a global function that I could really screw up if I started tinkering with it. My thoughts were that it would be better to create a new block files to replace this one and change the submit button to directly call the box and ajax function and send the information that we need to perform our checks. Then we could deactivate the original block (price) and create a new block (newprice) in the admincp extensions and CMS to replace it. This was done and seemed to work well.

Now I had the info I needed to send to the privacy check function. I got everything set up and tried a test between two non-friends but it did not work. It was not because of any errors in the coding. It was because Phpfox has many checks and even though it passed this series of tests, more checks awaited it in the mail.service process file. These are checks that would not be easy to overcome without some major code hacking, and my objective was to do this without hacking the core code.

As I thought about a solution to this I settled upon a possible solution where I would change the conditions of the code temporarily by making the viewer and poster friends and the change them back to their original relationship after the message was sent. This is easy enough to do, just add the two records to the friends table within the first plugin and remove the friends table entry in a plugin somewhere after the message was sent. But to do that I needed a way to identify to the second plugin that these people were not previously friends. I was finally able to do this by setting a session variable and checking it if removal was required.
After this was in place I learned that there are more privacy checks within the process service file, so I had to invoke a similar process for temporarily changing the original user privacy setting. It also required a session variable to make sure we could undo what we were doing.

PHP:
// If the mod has added a friend to allow a message, we must remove the friend now
$bRemoveFriend Phpfox::getLib('session')->get('RemoveFriend');
if(
$bRemoveFriend)
{
    
// Remove friends
    
$this->database()->delete(Phpfox::getT('friend'), "user_id = " Phpfox::getUserId() . " AND friend_user_id = " $aVals['user_id']);
    
$this->database()->delete(Phpfox::getT('friend'), "user_id = " $aVals['user_id'] . " AND friend_user_id = " Phpfox::getUserId());
}

// If the mod changed the user privacy setting of the lister to allow this message, we must restore the original setting
$iUprivacy=Phpfox::getLib('session')->get('OriginalUserPrivacy');
if(
$iUprivacy>)
{
    
Phpfox::getLib('database')->update(Phpfox::getT('user_privacy'), array('user_value' => (int)$iUprivacy), 'user_id = ' $aVals['user_id'] . ' AND user_privacy = "mail.send_message"' );
}

// There is no more use for any of the session variables.  We must remove them.
Phpfox::getLib('session')->remove('RemoveFriend');
Phpfox::getLib('session')->remove('MailSource');
Phpfox::getLib('session')->remove('OriginalUserPrivacy'); 

With all of these changes in place I was able to successfully send a message from a marketplace listing to a non-friend.

You can find the files for this addon here, (after it is approved)

The files are:
1. Newprice.class.php which goes into module/marketplace/include/component/block folder.
2. Newprice.html.php which goes into module/marketplace/template/default/block folder.
3. mail.service_mail_canmessageuser_1.php goes into module/marketplace/include/plugin folder.
4. mail.service_process_add.php goes into module/marketplace/include/plugin folder.

With these in place, go to your admincp ->extensions-create component and make newprice a block. Then go to admincp->CMS add block and add the block that you just created to the marketplace view controller. You will also want to disable the price block. As always, you want to clear your cache before testing you new mod.

It may be a good idea to inform your users that they will now get messages on marketplace listing based upon the comment setting. Maybe change the language phrase where it says “Control who can comment on this listing.”

These plugins worked well for me the first time, but they don’t always. Sometimes it is necessary to cycle the admincp->development cache plugins setting.

If you try this mod, do so on a dev site first. I can’t really test everything that should be tested to assure that it will cause no problems. If you do try this and find issues with it please let me know.

web