/** * Updates the weight on a relation * @param {string} $asUserId * The id of the user on whose behalf the app will be updating the relation * @param {string} $toPublisherId * The publisher of the stream on the 'to' end of the reltion * @param {string} $toStreamName * The name of the stream on the 'to' end of the relation * @param {string} $type * The type of the relation * @param {string} $fromPublisherId * The publisher of the stream on the 'from' end of the reltion * @param {string} $fromStreamName * The name of the stream on the 'from' end of the reltion * @param {double} $weight * The new weight * @param {double} $adjustWeights=null * The amount to move the other weights by, to make room for this one * @param {array} $options=array() * An array of options that can include: * "skipAccess" => Defaults to false. If true, skips the access checks and just updates the weight on the relation * @return {array|boolean} * Returns false if the operation was canceled by a hook * Otherwise returns array with key "to" and value of type Streams_Message */ static function updateRelation($asUserId, $toPublisherId, $toStreamName, $type, $fromPublisherId, $fromStreamName, $weight, $adjustWeights = null, $options = array()) { self::getRelation($asUserId, $toPublisherId, $toStreamName, $type, $fromPublisherId, $fromStreamName, $relatedTo, $relatedFrom, $category, $stream, $options); if (!$relatedTo->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'relatedTo', 'criteria' => 'with those fields'), array('publisherId', 'name', 'type', 'toPublisherId', 'to_name')); } // if (!$relatedFrom->retrieve()) { // throw new Q_Exception_MissingRow( // array('table' => 'relatedFrom', 'criteria' => 'those fields'), // array('publisherId', 'name', 'type', 'fromPublisherId', 'from_name') // ); // } if (empty($options['skipAccess'])) { if (!$category->testWriteLevel('relations')) { throw new Users_Exception_NotAuthorized(); } } /** * @event Streams/updateRelation/$streamType {before} * @param {string} relatedTo * @param {string} relatedFrom * @param {string} asUserId * @param {double} weight * @param {double} previousWeight */ $previousWeight = $relatedTo->weight; $adjustWeightsBy = $weight < $previousWeight ? $adjustWeights : -$adjustWeights; if (Q::event("Streams/updateRelation/{$stream->type}", compact('relatedTo', 'relatedFrom', 'type', 'weight', 'previousWeight', 'adjustWeightsBy', 'asUserId'), 'before') === false) { return false; } if (!empty($adjustWeights) and is_numeric($adjustWeights) and $weight !== $previousWeight) { $criteria = array('toPublisherId' => $toPublisherId, 'toStreamName' => $toStreamName, 'type' => $type, 'weight' => $weight < $previousWeight ? new Db_Range($weight, true, false, $previousWeight) : new Db_Range($previousWeight, false, true, $weight)); Streams_RelatedTo::update()->set(array('weight' => new Db_Expression("weight + " . $adjustWeightsBy)))->where($criteria)->execute(); } $relatedTo->weight = $weight; $relatedTo->save(); // Send Streams/updatedRelateTo message to the category stream // node server will be notified by Streams_Message::post $message = Streams_Message::post($asUserId, $toPublisherId, $toStreamName, array('type' => 'Streams/updatedRelateTo', 'instructions' => Q::json_encode(compact('fromPublisherId', 'fromStreamName', 'type', 'weight', 'previousWeight', 'adjustWeightsBy', 'asUserId'))), true); // TODO: We are not yet sending Streams/updatedRelateFrom message to the other stream // because we might be changing a lot of weights, and we'd have to message a lot of streams. // This is better done in the background using Node.js after selecting using $criteria // When we implement this, we can introduce weight again in the relatedFrom table. /** * @event Streams/updateRelation/$streamType {after} * @param {string} relatedTo * @param {string} relatedFrom * @param {string} asUserId * @param {double} weight * @param {double} previousWeight */ Q::event("Streams/updateRelation/{$stream->type}", compact('relatedTo', 'relatedFrom', 'type', 'weight', 'previousWeight', 'adjustWeightsBy', 'asUserId'), 'after'); return $message; }
/** * Updates the weight on a relation * @param {string} $asUserId * The id of the user on whose behalf the app will be updating the relation * @param {string} $toPublisherId * The publisher of the stream on the 'to' end of the reltion * @param {string} $toStreamName * The name of the stream on the 'to' end of the relation * @param {string} $type * The type of the relation * @param {string} $fromPublisherId * The publisher of the stream on the 'from' end of the reltion * @param {string} $fromStreamName * The name of the stream on the 'from' end of the reltion * @param {double} $weight * The new weight * @param {double} [$adjustWeights=1] * The amount to move the other weights by, to make room for this one. * This should be a positive number - the direction of the shift is determined automatically. * Or, set to 0 to prevent moving the other weights. * @param {array} $options=array() * @param {boolean} [$options.skipAccess=false] If true, skips the access checks and just unrelates the stream from the category * @return {array|boolean} * Returns false if the operation was canceled by a hook * Otherwise returns array with key "to" and value of type Streams_Message */ static function updateRelation($asUserId, $toPublisherId, $toStreamName, $type, $fromPublisherId, $fromStreamName, $weight, $adjustWeights = 1, $options = array()) { self::getRelations($asUserId, $toPublisherId, $toStreamName, $type, $fromPublisherId, $fromStreamName, $relatedTo, $relatedFrom, $categories, $streams, $arrayField, $options); $relatedTo = reset($relatedTo); $relatedFrom = reset($relatedFrom); $category = reset($categories); $stream = reset($streams); if (!$relatedTo) { throw new Q_Exception_MissingRow(array('table' => 'relatedTo', 'criteria' => 'with those fields'), array('publisherId', 'name', 'type', 'toPublisherId', 'to_name')); } // if (!$relatedFrom->retrieve()) { // throw new Q_Exception_MissingRow( // array('table' => 'relatedFrom', 'criteria' => 'those fields'), // array('publisherId', 'name', 'type', 'fromPublisherId', 'from_name') // ); // } if (empty($options['skipAccess'])) { if (!$category->testWriteLevel('relations')) { throw new Users_Exception_NotAuthorized(); } } /** * @event Streams/updateRelation/$streamType {before} * @param {string} relatedTo * @param {string} relatedFrom * @param {string} asUserId * @param {double} weight * @param {double} previousWeight */ $previousWeight = $relatedTo->weight; if (empty($adjustWeights)) { $adjustWeights = 0; } if (!is_numeric($adjustWeights) or $adjustWeights < 0) { throw new Q_Exception_WrongType(array('fields' => 'adjustWeights', 'type' => 'a non-negative number')); } $adjustWeightsBy = $weight < $previousWeight ? $adjustWeights : -$adjustWeights; if (Q::event("Streams/updateRelation/{$stream->type}", compact('relatedTo', 'relatedFrom', 'type', 'weight', 'previousWeight', 'adjustWeightsBy', 'asUserId'), 'before') === false) { return false; } if ($adjustWeights and $weight !== $previousWeight) { $criteria = array('toPublisherId' => $toPublisherId, 'toStreamName' => $toStreamName, 'type' => $type, 'weight' => $weight < $previousWeight ? new Db_Range($weight, true, false, $previousWeight) : new Db_Range($previousWeight, false, true, $weight)); Streams_RelatedTo::update()->set(array('weight' => new Db_Expression("weight + " . $adjustWeightsBy)))->where($criteria)->execute(); } $relatedTo->weight = $weight; $relatedTo->save(); // Send Streams/updatedRelateTo message to the category stream // node server will be notified by Streams_Message::post $message = Streams_Message::post($asUserId, $toPublisherId, $toStreamName, array('type' => 'Streams/updatedRelateTo', 'instructions' => compact('fromPublisherId', 'fromStreamName', 'type', 'weight', 'previousWeight', 'adjustWeightsBy', 'asUserId')), true); /** * @event Streams/updateRelation/$categoryType {after} * @param {string} relatedTo * @param {string} relatedFrom * @param {string} asUserId * @param {double} weight * @param {double} previousWeight */ Q::event("Streams/updateRelation/{$category->type}", compact('relatedTo', 'relatedFrom', 'type', 'weight', 'previousWeight', 'adjustWeightsBy', 'asUserId'), 'after'); return $message; }