コード例 #1
0
ファイル: Streams.php プロジェクト: AndreyTepaykin/Platform
 /**
  * Make the stream a member of category or other aggregating stream,
  * First parameter set - where to add, Second parameter set - what to add
  * NOTE: this currently only works when fromPublisherId and toPublisherId are on same Q cluster
  * @method relate
  * @static
  * @param {string} $asUserId
  *  The user who is making aggreagtor operation on the stream (add stream to category)
  * @param {string} $toPublisherId
  *  The user who has published the category stream
  * @param {string|array} $toStreamName
  *  The name of the category stream. Pass an array of strings to relate a single stream
  *  to multiple categories, but in that case make sure fromStreamName is a string.
  * @param {string} $type
  *  The type of the relation
  * @param {string} $fromPublisherId
  *  The user who has published the member stream
  * @param {string} $fromStreamName
  *  The name of the member stream. Pass an array of strings to relate multiple streams
  *  to a single category, but in that case make sure toStreamName is a string.
  * @param {array} $options=array()
  *  An array of options that can include:
  * @param {boolean} [$options.skipAccess=false] If true, skips the access checks and just relates the stream to the category
  * @param {double|string} [$options.weight] Pass a numeric value here, or something like "max+1" to make the weight 1 greater than the current MAX(weight)
  * @return {array|boolean}
  *  Returns false if the operation was canceled by a hook
  *  Returns true if relation was already there
  *  Otherwise returns array with keys "messagesFrom" and "messageTo" and values of type Streams_Message
  */
 static function relate($asUserId, $toPublisherId, $toStreamName, $type, $fromPublisherId, $fromStreamName, $options = array())
 {
     self::getRelations($asUserId, $toPublisherId, $toStreamName, $type, $fromPublisherId, $fromStreamName, $relatedToArray, $relatedFromArray, $categories, $streams, $arrayField, $options);
     // calculate weights
     $calculateWeights = null;
     foreach (${$arrayField} as $sn) {
         if (isset($relatedToArray[$sn])) {
             continue;
         }
         if (!isset($relatedToArray[$sn])) {
             // at least one new relation will be inserted
             if (isset($options['weight'])) {
                 $parts = explode('+', "{$options['weight']}");
                 if (count($parts) > 1) {
                     $calculateWeights = $parts[1];
                     break;
                 }
             }
         }
     }
     if (isset($calculateWeights)) {
         if (!is_numeric($calculateWeights) or $calculateWeights <= 0) {
             throw new Q_Exception_WrongValue(array('field' => 'weight', 'range' => 'a positive numeric value'), 'weight');
         }
         $rows = Streams_RelatedTo::select('toStreamName, MAX(weight) w')->where(compact('toPublisherId', 'toStreamName', 'type'))->groupBy('toStreamName')->ignoreCache()->fetchAll(PDO::FETCH_ASSOC);
         $maxWeights = array();
         foreach ($rows as $r) {
             $maxWeights[$r['toStreamName']] = $r['w'];
         }
     }
     $newRT = array();
     $newRF = array();
     $weights2 = array();
     foreach (${$arrayField} as $sn) {
         if (isset($relatedToArray[$sn])) {
             continue;
         }
         $category = $arrayField === 'toStreamName' ? $categories[$sn] : reset($categories);
         $stream = $arrayField === 'fromStreamName' ? $streams[$sn] : reset($streams);
         /**
          * @event Streams/relateTo/$categoryType {before}
          * @param {array} relatedTo
          * @param {array} relatedFrom
          * @param {string} asUserId
          * @param {Streams_Stream} category
          * @param {Streams_Stream} stream
          * @return {false} To cancel further processing
          */
         if (false === Q::event("Streams/relateTo/{$category->type}", compact('asUserId', 'category', 'stream'), 'before')) {
             continue;
         }
         /**
          * @event Streams/relateFrom/$streamType {before}
          * @param {array} relatedTo
          * @param {array} relatedFrom
          * @param {string} asUserId
          * @param {Streams_Stream} category
          * @param {Streams_Stream} stream
          * @return {false} To cancel further processing
          */
         if (false === Q::event("Streams/relateFrom/{$stream->type}", compact('asUserId', 'category', 'stream'), 'before')) {
             continue;
         }
         $tsn = $arrayField === 'toStreamName' ? $sn : $toStreamName;
         $newRT[$sn] = $newRF[$sn] = compact('toPublisherId', 'type', 'fromPublisherId');
         if ($calculateWeights) {
             if (!isset($weights2[$tsn])) {
                 $weights2[$tsn] = isset($maxWeights[$tsn]) ? $maxWeights[$tsn] : 0;
             }
             $weights2[$tsn] += $calculateWeights;
             $newRT[$sn]['weight'] = $weights2[$tsn];
         } else {
             if (isset($options['weight'])) {
                 $weights2[$tsn] = $newRT[$sn]['weight'] = $options['weight'];
             }
         }
         foreach (array('toStreamName', 'fromStreamName') as $f) {
             $newRT[$sn][$f] = $newRF[$sn][$f] = $f === $arrayField ? $sn : ${$f};
         }
     }
     // Save all the relatedTo
     Streams_RelatedTo::insertManyAndExecute($newRT);
     Streams_RelatedFrom::insertManyAndExecute($newRF);
     foreach (${$arrayField} as $sn) {
         $category = $arrayField === 'toStreamName' ? $categories[$sn] : reset($categories);
         $stream = $arrayField === 'fromStreamName' ? $streams[$sn] : reset($streams);
         $weight = isset($options['weight']) && is_numeric($options['weight']) ? $options['weight'] : null;
         $weight = Q::ifset($weights2, $category->name, $weight);
         $fromUrl = $stream->url();
         $fromIcon = $stream->icon;
         $fromTitle = $stream->title;
         $fromType = $stream->type;
         $fromDisplayType = Streams_Stream::displayType($fromType);
         if (!$category) {
             continue;
         }
         $toUrl = $category->url();
         $toIcon = $category->icon;
         $toTitle = $category->title;
         $toType = $category->type;
         $toDisplayType = Streams_Stream::displayType($toType);
         $parts = explode('/', $type);
         $displayType = substr(end($parts), 0, -1);
         $categoryName = explode('/', $category->name);
         $streamName = explode('/', $stream->name);
         $params = compact('relatedTo', 'relatedFrom', 'asUserId', 'category', 'stream', 'fromUrl', 'fromIcon', 'fromTitle', 'fromType', 'fromDisplayType', 'toUrl', 'toIcon', 'toTitle', 'toType', 'toDisplayType', 'displayType', 'categoryName', 'streamName');
         if ($u = Streams_Stream::getConfigField($category->type, array('relatedTo', $type, 'uri'), Streams_Stream::getConfigField($category->type, array('relatedTo', '*', 'uri', null)))) {
             $fromUrl = Q_Uri::url(Q_Handlebars::renderSource($u, $params));
         }
         if ($u = Streams_Stream::getConfigField($stream->type, array('relatedFrom', $type, 'uri'), Streams_Stream::getConfigField($stream->type, array('relatedFrom', '*', 'uri', null)))) {
             $toUrl = Q_Uri::url(Q_Handlebars::renderSource($u, $params));
         }
         $description = Q_Handlebars::renderSource(Streams_Stream::getConfigField($category->type, array('relatedTo', $type, 'description'), Streams_Stream::getConfigField($category->type, array('relatedTo', '*', 'description'), "New {$fromDisplayType} added")), $params);
         // Send Streams/relatedTo message to a stream
         // node server will be notified by Streams_Message::post
         // DISTRIBUTED: in the future, the publishers may be on separate domains
         // so posting this message may require internet communication.
         $instructions = compact('fromPublisherId', 'type', 'weight', 'displayType', 'fromUrl', 'toUrl', 'fromIcon', 'fromTitle', 'fromType', 'fromDisplayType', 'description');
         $instructions['fromStreamName'] = $stream->name;
         $relatedTo_messages[$toPublisherId][$category->name][] = array('type' => 'Streams/relatedTo', 'instructions' => $instructions);
         $description = Q_Handlebars::renderSource(Streams_Stream::getConfigField($stream->type, array('relatedFrom', $type, 'description'), Streams_Stream::getConfigField($stream->type, array('relatedFrom', '*', 'description'), "Added to {{toDisplayType}} as {$displayType}")), $params);
         // Send Streams/relatedFrom message to a stream
         // node server will be notified by Streams_Message::post
         // DISTRIBUTED: in the future, the publishers may be on separate domains
         // so posting this message may require internet communication.
         $instructions = compact('toPublisherId', 'type', 'weight', 'displayType', 'fromUrl', 'toUrl', 'toIcon', 'toTitle', 'toType', 'toDisplayType', 'description');
         $instructions['toStreamName'] = $category->name;
         $relatedFrom_messages[$fromPublisherId][$stream->name][] = array('type' => 'Streams/relatedFrom', 'instructions' => $instructions);
         /**
          * @event Streams/relateFrom/$streamType {after}
          * @param {string} relatedTo
          * @param {string} relatedFrom
          * @param {string} asUserId
          * @param {Streams_Stream} category
          * @param {Streams_Stream} stream
          */
         Q::event("Streams/relate/{$stream->type}", compact('relatedTo', 'relatedFrom', 'asUserId', 'category', 'stream'), 'after');
         /**
          * @event Streams/relateTo/$categoryType {after}
          * @param {string} relatedTo
          * @param {string} relatedFrom
          * @param {string} asUserId
          * @param {Streams_Stream} category
          * @param {Streams_Stream} stream
          */
         Q::event("Streams/relateTo/{$category->type}", compact('relatedTo', 'relatedFrom', 'asUserId', 'category', 'stream'), 'after');
     }
     list($messagesTo, $s) = Streams_Message::postMessages($asUserId, $relatedTo_messages, true);
     list($messagesFrom, $s) = Streams_Message::postMessages($asUserId, $relatedFrom_messages, true);
     return compact('messagesTo', 'messagesFrom');
 }