/ */ class Comment_Model_Comment extends P4Cms_Record { const STATUS_APPROVED = 'approved'; const STATUS_PENDING = 'pending'; const STATUS_REJECTED = 'rejected'; protected static $_storageSubPath = 'comments'; protected static $_idField = 'id'; protected static $_fields = array( 'id', 'user', 'name', 'comment', 'postTime' => array( 'accessor' => 'getPostTime', 'mutator' => 'setPostTime' ), 'votes' => array( 'accessor' => 'getVotes', 'mutator' => 'setVotes' ), 'status' => array( 'mutator' => 'setStatus' ) ); /** * Extend parent to join against users and expand user name * into full name and email where appropriate. * * @param P4Cms_Record_Query|array|null $query optional - query options to augment result. * @param P4Cms_Record_Adapter $adapter optional - storage adapter to use. * @return P4Cms_Model_Iterator all records of this type. */ public static function fetchAll($query = null, P4Cms_Record_Adapter $adapter = null) { // if no adapter given, use default. $adapter = $adapter ?: static::getDefaultAdapter(); // let parent do initial fetch. $comments = parent::fetchAll($query, $adapter); // fill in full-name and email of users if we have any comments. // we do this because comments from authenticated users are // stored without the full-name/email, just the username. if (count($comments)) { $p4 = $adapter->getConnection(); $result = $p4->run('users', $comments->invoke('getValue', array('user'))); $lookup = array(); foreach ($result->getData() as $user) { $lookup[$user['User']] = array( 'name' => $user['FullName'], 'email' => $user['Email'] ); } foreach ($comments as $comment) { if (isset($comment->user) && isset($lookup[$comment->user])) { $comment->setValues($lookup[$comment->user]); } } } return $comments; } /** * Get the recorded time this comment was posted. * * @return int the time this comment was allegedly posted. */ public function getPostTime() { return intval($this->_getValue('postTime')); } /** * Explicitly set the time that this comment was posted. * * @param int $time the time this comment was posted * @return Comment_Model_Comment provides fluent interface. */ public function setPostTime($time) { return $this->_setValue('postTime', $time); } /** * Get the votes counted for this comment. * * @return int the number of votes for this comment. */ public function getVotes() { return intval($this->_getValue('votes')); } /** * Explicitly set the number of votes for this comment * * @param int $votes the number of votes this comment should have. * @return Comment_Model_Comment provides fluent interface. */ public function setVotes($votes) { return $this->_setValue('votes', $votes); } /** * Adjust the number of votes on this comment up by one. * * @return Comment_Model_Comment provides fluent interface. */ public function voteUp() { return $this->setVotes($this->getVotes() + 1); } /** * Adjust the number of votes on this comment down by one. * * @return Comment_Model_Comment provides fluent interface. */ public function voteDown() { return $this->setVotes($this->getVotes() - 1); } /** * Set the status of this comment * * @param string $status the state to set this comment to. * @return Comment_Model_Comment provides fluent interface. * @throws InvalidArgumentException if given status is not a valid state. */ public function setStatus($status) { $states = array( static::STATUS_APPROVED, static::STATUS_PENDING, static::STATUS_REJECTED ); if (!in_array($status, $states, true)) { throw new InvalidArgumentException( "Cannot set status of comment. Given status is not a valid state." ); } return $this->_setValue('status', $status); } /** * Get all comments voted on by the given user under the given path. * * Any change that contains the word 'vote' in the description is * considered to be a vote. This is a rather fragile linkage. If the * change description for comment votes is altered, this will stop * working. * * Optimized to only lookup the comment ids. If you wish to read * other fields, you will incur a populate per comment. * * @param string $user the id of the user to fetch voted comments for. * @param string $path the path under which to fetch comments. * @param P4Cms_Record_Adapter $adapter optional - storage adapter to use. * @return P4Cms_Model_Iterator all comments voted on by the given user under the given path. * */ public static function fetchVotedComments($user, $path, P4Cms_Record_Adapter $adapter = null) { // if no adapter given, use default. $adapter = $adapter ?: static::getDefaultAdapter(); // ensure path has no trailing slash. $path = rtrim($path, '/'); // fetch all changes made by the given user against this path. $changes = P4_Change::fetchAll( array( P4_Change::FETCH_BY_USER => $user, P4_Change::FETCH_BY_FILESPEC => static::getStoragePath() . '/' . $path . '/...' ), $adapter->getConnection() ); // further limit changes to those with the word 'vote' in the description. $changes->filter( 'Description', 'Vote', array( P4_Model_Iterator::FILTER_NO_CASE, P4_Model_Iterator::FILTER_CONTAINS ) ); // if no changes, nothing more to query. if (!$changes->count()) { return new P4Cms_Model_Iterator; } // fetch comments affected by these changes. $ids = array_map('strval', $changes->invoke('getId')); $filter = new P4Cms_Record_Filter; $filter->addFstat('headChange', $ids); $comments = Comment_Model_Comment::fetchAll( array( 'filter' => $filter, 'paths' => array($path . '/...'), 'limitFields' => 'depotFile' ), $adapter ); return $comments; } }