function Streams_after_Streams_message_Streams_unrelatedTo($params)
{
    $message = $params['message'];
    $type = $message->getInstruction('type', null);
    $stream = $params['stream'];
    $rtypes = Q_Config::get('Streams', 'categorize', 'relationTypes', array());
    $stypes = Q_Config::get('Streams', 'categorize', 'streamTypes', array());
    if (!in_array($type, $rtypes) or !in_array($stream->type, $stypes)) {
        return;
    }
    $c = new Streams_Category();
    $c->publisherId = $stream->publisherId;
    $c->streamName = $stream->name;
    $fromPublisherId = $message->getInstruction('fromPublisherId', null);
    $fromStreamName = $message->getInstruction('fromStreamName', null);
    if (!isset($fromPublisherId) or !isset($fromStreamName)) {
        return;
    }
    // Begin database transaction
    $relatedTo = $c->retrieve(null, array('ignoreCache' => true, 'begin' => true)) ? json_decode($c->relatedTo, true) : array();
    if (isset($relatedTo[$type])) {
        foreach ($relatedTo[$type] as $weight => $info) {
            if ($info[0] === $fromPublisherId and $info[1] === $fromStreamName) {
                unset($relatedTo[$type][$weight]);
                break;
            }
        }
        $o = $message->getInstruction('options', null);
        $w = $message->getInstruction('weight', null);
        if (!empty($o['adjustWeights'])) {
            $rt = array();
            foreach ($relatedTo[$type] as $weight => $info) {
                if ($weight > $w) {
                    $rt[$weight - 1] = $info;
                } else {
                    $rt[$weight] = $info;
                }
            }
            $relatedTo[$type] = $rt;
        }
    }
    $c->relatedTo = Q::json_encode($relatedTo);
    $c->save();
    // End database transaction
}
function Streams_after_Streams_message_Streams_updateRelateTo($params)
{
    $message = $params['message'];
    $type = $message->getInstruction('type', null);
    $stream = $params['stream'];
    $rtypes = Q_Config::get('Streams', 'categorize', 'relationTypes', array());
    $stypes = Q_Config::get('Streams', 'categorize', 'streamTypes', array());
    if (!in_array($type, $rtypes) or !in_array($stream->type, $stypes)) {
        return;
    }
    $c = new Streams_Category();
    $c->publisherId = $stream->publisherId;
    $c->streamName = $stream->name;
    $fromPublisherId = $message->getInstruction('fromPublisherId', null);
    $fromStreamName = $message->getInstruction('fromStreamName', null);
    if (!isset($fromPublisherId) or !isset($fromStreamName)) {
        return;
    }
    // Begin database transaction
    $relatedTo = $c->retrieve(null, array('ignoreCache' => true, 'begin' => true)) ? json_decode($c->relatedTo, true) : array();
    $weight = (double) $message->getInstruction('weight', null);
    $previousWeight = (double) $message->getInstruction('previousWeight', null);
    $adjustWeightsBy = $message->getInstruction('adjustWeightsBy', null);
    if (isset($relatedTo[$type])) {
        $prev = $relatedTo[$type][$previousWeight];
        $rt = array();
        foreach ($relatedTo[$type] as $w => $info) {
            if ($weight < $previousWeight and ($w < $weight or $previousWeight <= $w)) {
                $rt[$w] = $info;
            } else {
                if ($weight >= $previousWeight and ($w <= $previousWeight or $weight < $w)) {
                    $rt[$w] = $info;
                } else {
                    $rt[$w + $adjustWeightsBy] = $info;
                }
            }
        }
        $rt[$weight] = $prev;
        $relatedTo[$type] = $rt;
    }
    $c->relatedTo = Q::json_encode($relatedTo);
    $c->save();
    // End database transaction
}
function Streams_after_Streams_message_Streams_relatedTo($params)
{
    $message = $params['message'];
    $type = $message->getInstruction('type', null);
    $stream = $params['stream'];
    $rtypes = Q_Config::get('Streams', 'categorize', 'relationTypes', array());
    $stypes = Q_Config::get('Streams', 'categorize', 'streamTypes', array());
    if (!in_array($type, $rtypes) or !in_array($stream->type, $stypes)) {
        return;
    }
    $c = new Streams_Category();
    $c->publisherId = $stream->publisherId;
    $c->streamName = $stream->name;
    $fromPublisherId = $message->getInstruction('fromPublisherId', null);
    $fromStreamName = $message->getInstruction('fromStreamName', null);
    if (!isset($fromPublisherId) or !isset($fromStreamName)) {
        return;
    }
    // Begin database transaction
    $relatedTo = $c->retrieve(null, array('ignoreCache' => true, 'begin' => true)) ? json_decode($c->relatedTo, true) : array();
    $weight = (double) $message->getInstruction('weight', null);
    if (!isset($weight)) {
        $rt = new Streams_RelatedTo();
        $rt->toPublisherId = $stream->publisherId;
        $rt->toStreamName = $stream->name;
        $rt->type = $type;
        $rt->fromPublisherId = $fromPublisherId;
        $rt->fromStreamName = $fromStreamName;
        $rt->retrieve(null, null, array('ignoreCache' => true));
        $weight = $rt->weight;
    }
    $fs = Streams::fetchOne($message->byUserId, $fromPublisherId, $fromStreamName);
    $weight = floor($weight);
    $relatedTo[$type][$weight] = array($fromPublisherId, $fromStreamName, $fs->title, $fs->icon);
    $c->relatedTo = Q::json_encode($relatedTo);
    $c->save(false, true);
    // End database transaction
}