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]);
      }
    }
    
  • 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
    (
    )
    
  • 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?

  • 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

  • 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.