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.

How to kick one or more Comments from CommentModel::Get

I have $Comments and want to delete some $Comment from them. The code by now is that:

      $CommentID = 100; // <- just some arbitrary number

      $CommentModel = new CommentModel();
      $Comments = $CommentModel->Get($DiscussionID);

      foreach ($Comments as $Comment) {
         if ($Comment->CommentID <= $CommentID) {
            $unset($Comment); // not working, because it does not change $Comments
            $Comment = NULL;  // not working for the same reason
         }
      }

The code in the loop doesn't work. It's obvious because they do not refer to the $Comments scope but only to the $Comment.
But there seems to be also another problem. Each $Comment is stored in an array [_Result] which is protected.
So I assumed I would have to "clone" the $Comments object, but a $MyComments = clone $Comments, also cloned the protected array.
This problem is far beyond my PHP knowledge. Can anyone guide me on how to achieve something like that?

Yes, I know I could try to achieve something like that with an $Offset in the Get-function, but I'd prefer getting all comments and sorting them out afterwards...

Best Answer

  • R_JR_J Admin
    Answer ✓

    YEAH! Garden is just too awesome:

          $Comments = $CommentModel->Get($DiscussionID);
          $CommentsFiltered = array();
          foreach ($Comments as $Comment) {
             if ($Comment->CommentID > $CommentID) {
                $CommentsFiltered[] = $Comment;
             }
          }
          $Comments->ImportDataset($CommentsFiltered);
    

    And that's it! :)

Answers

  • You want to remove the comment permanently from the db or just from your $Comments object?

    If it is the latter, something like this should work:

    foreach ($Comments as $Index => $Comment) {
      if ($Comment->CommentID <= $CommentID) {
        $unset($Comments[$Index]);
      }
    }
    

    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.

  • Yes, I just want to remove one or more comments from the $Comments object.
    Your code gives that error message Fatal error: Cannot use object of type Gdn_DataSet as array :(

  • I just tested this code against 2.0.18.10:

    $DiscussionID = 17;
    $Limit = 30;
    $CommentID = 100;
    
    $CommentModel = new CommentModel();
    $Comments = $CommentModel->Get($DiscussionID, $Limit)->Result();
    
    decho($Comments);
    foreach ($Comments as $Index => $Comment) {
      if ($Comment->CommentID <= $CommentID) {
        unset($Comments[$Index]);
      }
    }
    decho($Comments);
    

    Output from my install is:

    DEBUG: Array
    (
        [0] => stdClass Object
            (
                [CommentID] => 24
                [DiscussionID] => 17
                [InsertUserID] => 1
                [UpdateUserID] => 
                [DeleteUserID] => 
                [Body] => gvfsdg sdfsdf ad
                [Format] => Html
                [DateInserted] => 2014-01-20 19:16:18
                [DateDeleted] => 
                [DateUpdated] => 
                [InsertIPAddress] => 127.0.0.1
                [UpdateIPAddress] => 
                [Flag] => 0
                [Score] => 
                [Attributes] => 
                [InsertName] => hgtonight
                [InsertEmail] => hgtonight@daklutz.com
                [InsertPhoto] => 
                [UpdateName] => 
                [UpdateEmail] => 
                [UpdatePhoto] => 
            )
    
        [1] => stdClass Object
            (
                [CommentID] => 25
                [DiscussionID] => 17
                [InsertUserID] => 1
                [UpdateUserID] => 
                [DeleteUserID] => 
                [Body] => a fdsf dasf da f
                [Format] => Html
                [DateInserted] => 2014-01-20 19:16:20
                [DateDeleted] => 
                [DateUpdated] => 
                [InsertIPAddress] => 127.0.0.1
                [UpdateIPAddress] => 
                [Flag] => 0
                [Score] => 
                [Attributes] => 
                [InsertName] => hgtonight
                [InsertEmail] => hgtonight@daklutz.com
                [InsertPhoto] => 
                [UpdateName] => 
                [UpdateEmail] => 
                [UpdatePhoto] => 
            )
    
        [2] => stdClass Object
            (
                [CommentID] => 26
                [DiscussionID] => 17
                [InsertUserID] => 1
                [UpdateUserID] => 
                [DeleteUserID] => 
                [Body] => a fd adf ad
                [Format] => Html
                [DateInserted] => 2014-01-20 19:16:22
                [DateDeleted] => 
                [DateUpdated] => 
                [InsertIPAddress] => 127.0.0.1
                [UpdateIPAddress] => 
                [Flag] => 0
                [Score] => 
                [Attributes] => 
                [InsertName] => hgtonight
                [InsertEmail] => hgtonight@daklutz.com
                [InsertPhoto] => 
                [UpdateName] => 
                [UpdateEmail] => 
                [UpdatePhoto] => 
            )
    
    )
    
    DEBUG: Array
    (
    )
    

    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.

  • Get()->Result() does the job but I can't use it with my plugin by now /plugins/DiscussionRefresh/class.discussionrefresh.php:

    <?php if (!defined('APPLICATION')) exit();
    
    $PluginInfo['DiscussionRefresh'] = array(
       'Name' => 'Discussion Refresh',
       'Description' => 'Shows comments that have been posted to a discussion between opening it and pressing preview button',
       'Version' => '0.1',
        'RequiredApplications' => array('Vanilla' => '2.0.18'), 
       'HasLocale' => FALSE,
       'Author' => "Robin",
       'RegisterPermissions' => FALSE
    );
    
    class DiscussionRefreshPlugin extends Gdn_Plugin {
       // route all requests to /discussion/discussionrefreh/... to function Controller_...
       public function DiscussionController_DiscussionRefresh_Create($Sender, $Args) {
          return $this->Dispatch($Sender);
       }
    
       // default action is to return comments of a given discussion
       public function Controller_Index($Sender) {
          //get all comments of a discussion and return only the latest
          $Args = $Sender->RequestArgs;   
    
          // no request, no result
          if (count($Args) == 0)
             return FALSE;
    
          $DiscussionID = $Args[0];
          $CommentID = $Args[1];
    
          // check for proper discussionid
          if (!is_numeric($DiscussionID))
             return FALSE;
    
          $CommentModel = new CommentModel();
          $Comments = $CommentModel->Get($DiscussionID)->Result();
    
          // if no comment id is given, return all comments
          if (!is_numeric($CommentID))
             $CommentID = 0;
    
    decho($Comments);
          foreach ($Comments as $Index => $Comment) {
             if ($Comment->CommentID <= $CommentID) {
                unset($Comments[$Index]);
             }
          }
    decho($Comments);
    
          $Sender->SetData('CommentData', $Comments, TRUE);
          //$Sender->DeliveryType = 'VIEW';
          //&DeliveryMethod=JSON
          $Sender->Render($Sender->FetchViewLocation('comments', 'discussion'));
       }
    }
    

    I need an object, as far as I can see, if I want to reuse the standard comment views

  • Ahh... now there is the rub. The default view assumes a gdn_dataset object is being passed. It calls Result on the passed object. You could create a wrapper object that contains a Result method on it that just returns the array. Something like this:

    class CommentSliceWrapper {
      private $_Comments;
    
      public function SetData($commentArray) {
        $this->_Comments = $commentArray;
      }
    
      public function Result() {
        return $this->_Comments;
      }
    }
    

    The bigger question I am asking, is why not retrieve the entire discussion view (which will handle the entire rendering of the view) and then slice it in JS?

    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.

  • I just found that function in class.dataset.php and now I'm trying to go that way:

       /**
        * Allows you to fill this object's result set with a foreign data set in
        * the form of an array of associative arrays (or objects).
        *
        * @param array $Resultset The array of arrays or objects that represent the data to be traversed.
        */
       public function ImportDataset($Resultset) {
    ...
    

    I took your advice to fetch all comments for the caching benefit. But returning all comments and throwing most of them away after transfering them to the client would be a waste of bandwidth. It also takes longer to render each comment instead of just rendering what is needed.

  • Good point on the rendering aspect. :D

    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.

  • R_JR_J Admin
    Answer ✓

    YEAH! Garden is just too awesome:

          $Comments = $CommentModel->Get($DiscussionID);
          $CommentsFiltered = array();
          foreach ($Comments as $Comment) {
             if ($Comment->CommentID > $CommentID) {
                $CommentsFiltered[] = $Comment;
             }
          }
          $Comments->ImportDataset($CommentsFiltered);
    

    And that's it! :)

  • @hgtonight: thanks for your help, again!

  • And I'm happy Garden has a simple way to solve a problem that I still could not solve with simple php...

Sign In or Register to comment.