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

Messing with activities

Hello guys, it's again me with another research going on.

I'm trying to understand how to create an activity, but the documentation is empty on this one and the vanilla source code is getting me confused.

At first I saw this usage in commentmodel:

      $ActivityModel = new ActivityModel();
     $Activity = array(
        'ActivityType' => 'Comment',
        'ActivityUserID' => $Fields['InsertUserID'],
        'HeadlineFormat' => $HeadlineFormat,
        'RecordType' => 'Comment',
        'RecordID' => $CommentID,
        'Route' => "/discussion/comment/$CommentID#Comment_$CommentID",
        'Data' => array(
           'Name' => $Discussion->Name,
           'Category' => GetValue('Name', $Category)
        )
     );
  $ActivityModel->Queue($Activity, 'DiscussionComment');


OK so from this I understand that there are the following fields:

ActivityType= Probably one of the activities from the ActivityType table in the database, it finds it based on ActivityName? Do I have to add an activity type?

ActivityUserID = Who "initiated" the activity.

Headlineformat = What message to display.

RecordType = Unsure about this.. is this like the type of the record that calls the activity, as if I were to notify about something in a discussion I would put Discussion?

RecordID= the ID of where activity took place.

Route= link to the thing we notify about

Data= ??? Used for formatting the message?

So now I read the discussionmodel usage:

              $Activity = array(
              'ActivityType' => 'Discussion',
              'ActivityUserID' => $Fields['InsertUserID'],
              'HeadlineFormat' => $HeadlineFormat,
              'RecordType' => 'Discussion',
              'RecordID' => $DiscussionID,
              'Route' => DiscussionUrl($Fields),
              'Data' => array(
                 'Name' => $DiscussionName,
                 'Category' => GetValue('Name', $Category)
              )
           );
                ...................
              $Activity['HeadlineFormat'] = T('HeadlineFormat.Mention', '{ActivityUserID,user} mentioned you in <a href="{Url,html}">{Data.Name,text}</a>');
              $Activity['NotifyUserID'] = GetValue('UserID', $User);
              $ActivityModel->Queue($Activity, 'Mention');


OK Now we see the ActivityType is Discussion, but when it queues it puts in second parameter Mention?

I go to the ActivityType Table, no activitytype called Mention? Only DiscussionMention and CommentMention

but ActivityType in the array is 'Discussion'? so neither options I had in mind that are used to identify ActivityType are invalid in this case..

Also what's the RouteCode in ActivityType table?

Thanks in advance! and sorry if I got you an headache

«1

Comments

  • The route is the URL the activity should link to. In this case it is the discussions URL.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • @hgtonight:
    I asked about the RouteCode column in the table.

  • You need a better IDE for code inspection, methinks. Go to the 'Queue' method in the ActivityModel to learn about the second parameter ('Mention').

    Your inferences about RecordType and Data are correct.

    'Discussion' and 'Comment' are special ActivityTypes used for the Advanced Notifications, I believe.

  • @Lincoln, mind sharing some insight on the differences between notifications and advanced notifications?

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • @hgtonight said:
    Lincoln, mind sharing some insight on the differences between notifications and advanced notifications?

    My finding, with Vanilla 2.0.x was that "advanced notifications" allows users to receive a notifications when a new discussion is posted in a forum. It would be interesting to see if they can do more than that.

  • Yes, Garden.AdvancedNotifications.View is the permission governing the ability to receive per-category notifications of any new discussions and/or comment. They operate differently than the normal notifications under Edit Preferences and appear under the sub-heading "Category Notifications".

    As an aside, Advanced Notifications does not scale. It's for admins & mods only.

  • @Lincoln,

    Thanks for your comment. I'll try the things out.

    About IDE, do you have any recommendation ? until now I used gedit .. I tried some of the PHP IDES but they were pretty useless in other development enviroments (not vanilla)

  • peregrineperegrine MVP
    edited December 2013

    @Aviram said:
    Lincoln,

    Thanks for your comment. I'll try the things out.

    About IDE, do you have any recommendation ? until now I used gedit .. I tried some of the PHP IDES but they were pretty useless in other development enviroments (not vanilla)

    try netbeans, easier to set up than eclipse for php, it seems. I use grep mostly though.

    I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.

  • @Aviram said:
    About IDE, do you have any recommendation ?

    I am really liking netbeans 7.4. So there is another vote for it.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

  • @Aviram Several Vanilla devs use NetBeans. I find PhpStorm to be the best.

  • If I skip adding an activity to the database and I use the comment and discussion activity types, would that cause issues later on?

  • NVM my last comment, I just added tables and used them.
    I cannot find tho how to add a preference so I can use it when calling Save .. so right now I'm using DiscussionComment in order to make it notify users

  • @hgtonight said:

    Did you want each user to be able to configure their notifications? I see you have it listed as a todo at top. If you want to add in a notification preference, use something like below:

    public function ProfileController_AfterPreferencesDefined_Handler($Sender) {
      $Sender->Preferences['Notifications']['Popup.ProfileVisitors'] = T('Notify me when people visit my profile.');
      // Doesn't seem like you would want an email notification, but this is how to add it anyway
      // $Sender->Preferences['Notifications']['Email.ProfileVisitors'] = T('Notify me when people visit my profile.');
    }
    

    Not quite sure what you are talking about, but maybe that piece of code could help you. Do you want to create a custom Activity? I've tried that recently and gave it up, but here's what I've found out (you would have to change "ProfileVisitors" in the above by "YourActivity" name).

    First you have to create a new Activity. There seems to be no function for that, so you have to use SQL. I've no clue what each of the columns do but I add my guesses

    // check if there is already an activity type for YourActivity
    if ($SQL->GetWhere('ActivityType', array('Name' => 'YourActivity'))->NumRows() == 0)
       // if not, create it.
       $SQL->Insert('ActivityType', // table to insert into
          array('Name' => 'YourActivity', 
             'AllowComments' => '0', // allow users to comment below activities
             'FullHeadline' => 'FullHeadline: %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s.', // the message to show. See below for the meaning of the variables. Not sure when Full- and when ProfileHeadline is shown
             'ProfileHeadline' => 'ProfileHeadline: %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s.',
             'RouteCode' => 'profile', // I guess it's a link to the controller?
             'Notify' => '1', // maybe the default behaviour?
             'Public' => '0' // 1 will make it a wall post that anyone can see
          ));
    

    Here are the variables

    • %1 = ActivityName
    • %2 = ActivityName Possessive: Username
    • %3 = RegardingName
    • %4 = RegardingName Possessive: Username, his, her, your
    • %5 = Link to RegardingName's Wall
    • %6 = his/her
    • %7 = he/she
    • %8 = RouteCode & Route

    Then you have the function AddActivity in functions.general.php that you can use

    if (!function_exists('AddActivity')) {
       /**
    * A convenience function that allows adding to the activity table with a single line.
    */
       function AddActivity($ActivityUserID, $ActivityType, $Story = '', $RegardingUserID = '', $Route = '', $SendEmail = '') {
          $ActivityModel = new ActivityModel();
          return $ActivityModel->Add($ActivityUserID, $ActivityType, $Story, $RegardingUserID, '', $Route, $SendEmail);
       }
    }
    

    But I do not know if there is anything else to take into consideration

  • Hey @R_J !

    Thanks for your comment. I've successfully added an activity and used it but I can't figure how to add it's own preferences, so when I call the Save method on ActivityModel it'd notify the user or not notify, depending on his specific settings for that type of activity. for now I'm using the DiscussionComment perference and my own activity.

    I guess I would want to change it if it's possible so it will have seperate notification preference.

  • Have you seen the first snippet of code? Add this to your plugin and a user can set notifications preferences for your activity in his profile:

    public function ProfileController_AfterPreferencesDefined_Handler($Sender) {
       $Sender->Preferences['Notifications']['Popup.YourActivity'] = T('Whatever it is good for');
       $Sender->Preferences['Notifications']['Email.YourActivity'] = T('Whatever it is good for');
    }
    
  • Oh I didn't notice! I'll try that out.

    How do I set the default preferences to be notify, or I don't need to do that?

  • Please tell me, if you know how ;)

    But from looking at the code of the activitymodel it could be that you have to call SaveToConfig('Preferences.Email.YourActivity', TRUE); and SaveToConfig('Preferences.Popup.YourActivity', TRUE); in your Setup() and that's it.

  • Got it working :-)

    <?php if (!defined('APPLICATION')) exit();
    
    $PluginInfo['ActivityTest'] = array(
       'Name' => 'Activity Test',
       'Description' => 'Test Activity and Notification Feature',
       'Version' => '0.1',
       'Author' => 'Robin'
    );
    
    class ActivityTestPlugin extends Gdn_Plugin {
       public function Setup() {
          $Sql = Gdn::SQL();
          // check if there is already an activity type for YourActivity
          if ($Sql->GetWhere('ActivityType', array('Name' => 'ActivityTest'))->NumRows() == 0) {
             // if not, create it.
             $Sql->Insert('ActivityType', // table to insert into
                array('Name' => 'ActivityTest',
                   'AllowComments' => '0', // allow users to comment below activities
                   'FullHeadline' => '%1$s looked at a %8$s.', // the message to show. See below for the meaning of the variables. Not sure when Full- and when ProfileHeadline is shown
                   'ProfileHeadline' => 'ProfileHeadline: %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s.',
                   'RouteCode' => 'Discussion', // Name of the link (Route) that could be passed to the activity
                   'Notify' => '1', // maybe the default behaviour?
                   'Public' => '1' // 1 will make it a wall post that anyone can see
                ));
          }
          SaveToConfig('Preferences.Popup.ActivityTest', TRUE);
          SaveToConfig('Preferences.Email.ActivityTest', TRUE);
       }
       public function ProfileController_AfterPreferencesDefined_Handler($Sender) {
          $Sender->Preferences['Notifications']['Popup.ActivityTest'] = T('Notify me when test event happens');
          $Sender->Preferences['Notifications']['Email.ActivityTest'] = T('Notify me when test event happens');
       }
    
       public function DiscussionController_Render_Before($DiscussionController) {
          $DiscussionID = $DiscussionController->DiscussionID;
          $ActivityUserID = Gdn::Session()->UserID; // current user
    
          $ActivityType = 'ActivityTest';
          $Story = 'Some additional text to display under the Headline'; // use default Story
          $RegardingUserID = 1; // in this case the admin
          $CommentActivityID = '';
          $Route = '/discussion/'.$DiscussionID;
          $SendEmail = ''; // use default setting
    
          $ActivityModel = new ActivityModel();
          $ActivityID = $ActivityModel->Add(
             $ActivityUserID,
             $ActivityType,
             $Story,
             $RegardingUserID,
             $CommentActivityID,
             $Route,
             $SendEmail
          );
          $ActivityModel->SendNotification($ActivityID, $Story);
       }
    }
    
  • I have to add: it is working somehow, but I do not know how exactly

  • I recently worked with activities on Yaga. This is the code I use to notify people of badge awards:

    // Record some activity
    $ActivityModel = new ActivityModel();
    
    $Activity = array(
      'ActivityType' => 'BadgeAward',
      'ActivityUserID' => Gdn::Session()->UserID,
      'RegardingUserID' => $UserID,
      'Photo' => '/uploads/' . $Badge->Photo,
      'RecordType' => 'Badge',
      'RecordID' => $BadgeID,
      'Route' => '/badges/detail/' . $Badge->BadgeID . '/' . Gdn_Format::Url($Badge->Name),
      'HeadlineFormat' => T('Yaga.HeadlineFormat.BadgeEarned'),
      'Data' => array(
        'Name' => $Badge->Name
      ),
      'Story' => $Badge->Description
    );
    
    $ActivityModel->Queue($Activity);
    
    // Notify the user of the award
    $Activity['NotifyUserID'] = $UserID;
    $Activity['Emailed'] = ActivityModel::SENT_PENDING;
    $ActivityModel->Queue($Activity, 'Badges', array('Force' => TRUE));
    

    As far as I can tell, this forces the activity to abide by the user's notifications preferences.

    Search first

    Check out the Documentation! We are always looking for new content and pull requests.

    Click on insightful, awesome, and funny reactions to thank community volunteers for their valuable posts.

Sign In or Register to comment.