| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * StatusNet, the distributed open-source microblogging tool | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * An activity | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * PHP version 5 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LICENCE: This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  |  * (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @category  Feed | 
					
						
							|  |  |  |  * @package   StatusNet | 
					
						
							|  |  |  |  * @author    Evan Prodromou <evan@status.net> | 
					
						
							|  |  |  |  * @author    Zach Copley <zach@status.net> | 
					
						
							|  |  |  |  * @copyright 2010 StatusNet, Inc. | 
					
						
							|  |  |  |  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPLv3 | 
					
						
							|  |  |  |  * @link      http://status.net/ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if (!defined('STATUSNET')) { | 
					
						
							|  |  |  |     exit(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ActivityContext | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     public $replyToID; | 
					
						
							|  |  |  |     public $replyToUrl; | 
					
						
							|  |  |  |     public $location; | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |     public $attention = array();    // 'uri' => 'type'
 | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  |     public $conversation; | 
					
						
							| 
									
										
										
										
											2013-06-07 03:11:23 -04:00
										 |  |  |     public $scope; | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const THR     = 'http://purl.org/syndication/thread/1.0'; | 
					
						
							|  |  |  |     const GEORSS  = 'http://www.georss.org/georss'; | 
					
						
							|  |  |  |     const OSTATUS = 'http://ostatus.org/schema/1.0'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |     const INREPLYTO  = 'in-reply-to'; | 
					
						
							|  |  |  |     const REF        = 'ref'; | 
					
						
							|  |  |  |     const HREF       = 'href'; | 
					
						
							| 
									
										
										
										
											2014-11-27 13:39:38 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // OStatus element names with prefixes
 | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |     const OBJECTTYPE = 'ostatus:object-type';   // FIXME: Undocumented!
 | 
					
						
							| 
									
										
										
										
											2014-11-27 13:39:38 +01:00
										 |  |  |     const CONVERSATION = 'ostatus:conversation'; | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const POINT     = 'point'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-02 14:06:14 -04:00
										 |  |  |     const MENTIONED    = 'mentioned'; | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |     const ATTN_PUBLIC  = 'http://activityschema.org/collection/public'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-13 16:23:10 -04:00
										 |  |  |     function __construct($element = null) | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-09-13 16:23:10 -04:00
										 |  |  |         if (empty($element)) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  |         $replyToEl = ActivityUtils::child($element, self::INREPLYTO, self::THR); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!empty($replyToEl)) { | 
					
						
							|  |  |  |             $this->replyToID  = $replyToEl->getAttribute(self::REF); | 
					
						
							|  |  |  |             $this->replyToUrl = $replyToEl->getAttribute(self::HREF); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $this->location = $this->getLocation($element); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-27 13:39:38 +01:00
										 |  |  |         $convs = $element->getElementsByTagNameNS(self::OSTATUS, self::CONVERSATION); | 
					
						
							|  |  |  |         foreach ($convs as $conv) { | 
					
						
							|  |  |  |             $this->conversation = $conv->textContent; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (empty($this->conversation)) { | 
					
						
							|  |  |  |             // fallback to the atom:link rel="ostatus:conversation" element
 | 
					
						
							|  |  |  |             $this->conversation = ActivityUtils::getLink($element, self::CONVERSATION); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // Multiple attention links allowed
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $links = $element->getElementsByTagNameNS(ActivityUtils::ATOM, ActivityUtils::LINK); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for ($i = 0; $i < $links->length; $i++) { | 
					
						
							|  |  |  |             $link = $links->item($i); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |             $linkRel  = $link->getAttribute(ActivityUtils::REL); | 
					
						
							|  |  |  |             $linkHref = $link->getAttribute(self::HREF); | 
					
						
							|  |  |  |             if ($linkRel == self::MENTIONED && $linkHref !== '') { | 
					
						
							|  |  |  |                 $this->attention[$linkHref] = $link->getAttribute(ActivityContext::OBJECTTYPE); | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Parse location given as a GeoRSS-simple point, if provided. | 
					
						
							|  |  |  |      * http://www.georss.org/simple | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param feed item $entry | 
					
						
							|  |  |  |      * @return mixed Location or false | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     function getLocation($dom) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $points = $dom->getElementsByTagNameNS(self::GEORSS, self::POINT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for ($i = 0; $i < $points->length; $i++) { | 
					
						
							|  |  |  |             $point = $points->item($i)->textContent; | 
					
						
							|  |  |  |             return self::locationFromPoint($point); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // XXX: Move to ActivityUtils or Location?
 | 
					
						
							|  |  |  |     static function locationFromPoint($point) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $point = str_replace(',', ' ', $point); // per spec "treat commas as whitespace"
 | 
					
						
							|  |  |  |         $point = preg_replace('/\s+/', ' ', $point); | 
					
						
							|  |  |  |         $point = trim($point); | 
					
						
							|  |  |  |         $coords = explode(' ', $point); | 
					
						
							|  |  |  |         if (count($coords) == 2) { | 
					
						
							|  |  |  |             list($lat, $lon) = $coords; | 
					
						
							|  |  |  |             if (is_numeric($lat) && is_numeric($lon)) { | 
					
						
							|  |  |  |                 common_log(LOG_INFO, "Looking up location for $lat $lon from georss point"); | 
					
						
							|  |  |  |                 return Location::fromLatLon($lat, $lon); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         common_log(LOG_ERR, "Ignoring bogus georss:point value $point"); | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-02-18 00:51:08 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns context (StatusNet stuff) as an array suitable for serializing | 
					
						
							|  |  |  |      * in JSON. Right now context stuff is an extension to Activity. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array the context | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 00:51:08 -08:00
										 |  |  |     function asArray() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $context = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 18:52:49 -08:00
										 |  |  |         $context['inReplyTo']    = $this->getInReplyToArray(); | 
					
						
							| 
									
										
										
										
											2011-02-18 00:51:08 -08:00
										 |  |  |         $context['conversation'] = $this->conversation; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return array_filter($context); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Returns an array of arrays representing Activity Objects (intended to be | 
					
						
							|  |  |  |      * serialized in JSON) that represent WHO the Activity is supposed to | 
					
						
							|  |  |  |      * be received by. This is not really specified but appears in an example | 
					
						
							|  |  |  |      * of the current spec as an extension. We might want to figure out a JSON | 
					
						
							|  |  |  |      * serialization for OStatus and use that to express mentions instead. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * XXX: People's ideas on how to do this are all over the place | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array the array of recipients | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 00:51:08 -08:00
										 |  |  |     function getToArray() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $tos = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |         foreach ($this->attention as $attnUrl => $attnType) { | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  |             $to = array( | 
					
						
							| 
									
										
										
										
											2013-10-28 22:21:14 +01:00
										 |  |  |                 'objectType' => $attnType,  // can be empty
 | 
					
						
							|  |  |  |                 'id'         => $attnUrl, | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  |             ); | 
					
						
							| 
									
										
										
										
											2011-02-18 00:51:08 -08:00
										 |  |  |             $tos[] = $to; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $tos; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 18:52:49 -08:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Return an array for the notices this notice is a reply to  | 
					
						
							|  |  |  |      * suitable for serializing as JSON note objects. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array the array of notes | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      function getInReplyToArray() | 
					
						
							|  |  |  |      { | 
					
						
							| 
									
										
										
										
											2011-02-18 18:52:49 -08:00
										 |  |  |          if (empty($this->replyToID) && empty($this->replyToUrl)) { | 
					
						
							|  |  |  |              return null; | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 18:52:49 -08:00
										 |  |  |          $replyToObj = array('objectType' => 'note'); | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 18:52:49 -08:00
										 |  |  |          // XXX: Possibly shorten this to just the numeric ID?
 | 
					
						
							|  |  |  |          //      Currently, it's the full URI of the notice.
 | 
					
						
							|  |  |  |          if (!empty($this->replyToID)) { | 
					
						
							|  |  |  |              $replyToObj['id'] = $this->replyToID; | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  |          if (!empty($this->replyToUrl)) { | 
					
						
							|  |  |  |              $replyToObj['url'] = $this->replyToUrl; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-18 18:52:49 -08:00
										 |  |  |          return $replyToObj; | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  |      } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-20 16:06:22 -05:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-02-18 10:02:41 -08:00
										 |  |  | 
 |