/** * If the user is participating in the stream, sets state of participant row * as "left" and posts a "Streams/leave" type message to the stream * @method leave * @param $options=array() {array} * An associative array of options. The keys can be:<br/> * "userId": The user who is leaving the stream. Defaults to the logged-in user. * "skipAccess": if true, skip access check for whether user can join * @param $participant=null {reference} * Optional reference to a participant object that will be filled * to point to the participant object, if any. * @return {boolean} */ function leave($options = array(), &$participant = null) { $stream = $this->fetchAsUser($options, $userId); if (empty($options['skipAccess']) and !$stream->testWriteLevel('join')) { if (!$stream->testReadLevel('see')) { throw new Streams_Exception_NoSuchStream(); } throw new Users_Exception_NotAuthorized(); } $participant = new Streams_Participant(); $participant->publisherId = $stream->publisherId; $participant->streamName = $stream->name; $participant->userId = $userId; if (!$participant->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'participant', 'criteria' => "userId = {$userId}, publisherId = {$stream->publisherId}, name = {$stream->name}")); } // Remove from participant list if ($participant->state === 'left') { return false; } $participant->state = 'left'; if (!$participant->save()) { return false; } Q_Utils::sendToNode(array("Q/method" => "Streams/Stream/leave", "participant" => Q::json_encode($participant->toArray()), "stream" => Q::json_encode($stream->toArray()))); // Post Streams/leave message to the stream $stream->post($userId, array('type' => 'Streams/leave'), true); // Now post Streams/left message to Streams/participating Streams_Message::post($userId, $userId, 'Streams/participating', array('type' => 'Streams/left', 'content' => '', 'instructions' => Q::json_encode(array('publisherId' => $stream->publisherId, 'streamName' => $stream->name))), true); return true; }