Merge remote branch 'origin/1.0.x' into 1.0.x
This commit is contained in:
		
							
								
								
									
										16
									
								
								EVENTS.txt
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								EVENTS.txt
									
									
									
									
									
								
							@@ -1115,3 +1115,19 @@ StartGroupProfileElements: Start showing stuff about the group on its profile pa
 | 
			
		||||
EndGroupProfileElements: Start showing stuff about the group on its profile page
 | 
			
		||||
- $action: action being executed (for output and params)
 | 
			
		||||
- $group: group for the page
 | 
			
		||||
 | 
			
		||||
StartActivityObjectOutputAtom: Called at start of Atom XML output generation for ActivityObject chunks, just inside the <activity:object>. Cancel the event to take over its output completely (you're responsible for calling the matching End event if so)
 | 
			
		||||
- $obj: ActivityObject
 | 
			
		||||
- $out: XMLOutputter to append custom output
 | 
			
		||||
 | 
			
		||||
EndActivityObjectOutputAtom: Called at end of Atom XML output generation for ActivityObject chunks, just inside the </activity:object>
 | 
			
		||||
- $obj: ActivityObject
 | 
			
		||||
- $out: XMLOutputter to append custom output
 | 
			
		||||
 | 
			
		||||
StartActivityObjectOutputJson: Called at start of JSON output generation for ActivityObject chunks: the array has not yet been filled out. Cancel the event to take over its output completely (you're responsible for calling the matching End event if so)
 | 
			
		||||
- $obj ActivityObject
 | 
			
		||||
- &$out: array to be serialized; you're free to modify it
 | 
			
		||||
 | 
			
		||||
EndActivityObjectOutputJson: Called at end of JSON output generation for ActivityObject chunks: the array has not yet been filled out.
 | 
			
		||||
- $obj ActivityObject
 | 
			
		||||
- &$out: array to be serialized; you're free to modify it
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										50
									
								
								js/util.js
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								js/util.js
									
									
									
									
									
								
							@@ -423,7 +423,6 @@ var SN = { // StatusNet
 | 
			
		||||
                                        .css({display:'none'})
 | 
			
		||||
                                        .fadeIn(2500);
 | 
			
		||||
                                    SN.U.NoticeWithAttachment($('#'+notice.id));
 | 
			
		||||
                                    SN.U.NoticeReplyTo($('#'+notice.id));
 | 
			
		||||
                                    SN.U.switchInputFormTab("placeholder");
 | 
			
		||||
                                }
 | 
			
		||||
                            } else {
 | 
			
		||||
@@ -516,34 +515,22 @@ var SN = { // StatusNet
 | 
			
		||||
         * @access private
 | 
			
		||||
         */
 | 
			
		||||
        NoticeReply: function() {
 | 
			
		||||
            if ($('#content .notice_reply').length > 0) {
 | 
			
		||||
                $('#content .notice').each(function() { SN.U.NoticeReplyTo($(this)); });
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Setup function -- DOES NOT trigger actions immediately.
 | 
			
		||||
         *
 | 
			
		||||
         * Sets up event handlers on the given notice's reply button to
 | 
			
		||||
         * tweak the new-notice form with needed variables and focus it
 | 
			
		||||
         * when pushed.
 | 
			
		||||
         *
 | 
			
		||||
         * (This replaces the default reply button behavior to submit
 | 
			
		||||
         * directly to a form which comes back with a specialized page
 | 
			
		||||
         * with the form data prefilled.)
 | 
			
		||||
         *
 | 
			
		||||
         * @param {jQuery} notice: jQuery object containing one or more notices
 | 
			
		||||
         * @access private
 | 
			
		||||
         */
 | 
			
		||||
        NoticeReplyTo: function(notice) {
 | 
			
		||||
            notice.find('.notice_reply').live('click', function(e) {
 | 
			
		||||
            $('#content .notice_reply').live('click', function(e) {
 | 
			
		||||
                e.preventDefault();
 | 
			
		||||
                var notice = $(this).closest('li.notice');
 | 
			
		||||
                var nickname = ($('.author .nickname', notice).length > 0) ? $($('.author .nickname', notice)[0]) : $('.author .nickname.uid');
 | 
			
		||||
                SN.U.NoticeInlineReplyTrigger(notice, '@' + nickname.text());
 | 
			
		||||
                return false;
 | 
			
		||||
            });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Stub -- kept for compat with plugins for now.
 | 
			
		||||
         * @access private
 | 
			
		||||
         */
 | 
			
		||||
        NoticeReplyTo: function(notice) {
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Open up a notice's inline reply box.
 | 
			
		||||
         *
 | 
			
		||||
@@ -640,26 +627,23 @@ var SN = { // StatusNet
 | 
			
		||||
                                    '<input class="placeholder">' +
 | 
			
		||||
                                '</li>');
 | 
			
		||||
            placeholder.find('input')
 | 
			
		||||
                .val(SN.msg('reply_placeholder'))
 | 
			
		||||
                .focus(function() {
 | 
			
		||||
                    SN.U.NoticeInlineReplyTrigger(notice);
 | 
			
		||||
                    return false;
 | 
			
		||||
                });
 | 
			
		||||
                .val(SN.msg('reply_placeholder'));
 | 
			
		||||
            list.append(placeholder);
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Setup function -- DOES NOT apply immediately.
 | 
			
		||||
         *
 | 
			
		||||
         * Sets up event handlers for favor/disfavor forms to submit via XHR.
 | 
			
		||||
         * Sets up event handlers for inline reply mini-form placeholders.
 | 
			
		||||
         * Uses 'live' rather than 'bind', so applies to future as well as present items.
 | 
			
		||||
         */
 | 
			
		||||
        NoticeInlineReplySetup: function() {
 | 
			
		||||
            $('.threaded-replies').each(function() {
 | 
			
		||||
                var list = $(this);
 | 
			
		||||
                var notice = list.closest('.notice');
 | 
			
		||||
                SN.U.NoticeInlineReplyPlaceholder(notice);
 | 
			
		||||
            });
 | 
			
		||||
            $('li.notice-reply-placeholder input')
 | 
			
		||||
                .live('focus', function() {
 | 
			
		||||
                    var notice = $(this).closest('li.notice');
 | 
			
		||||
                    SN.U.NoticeInlineReplyTrigger(notice);
 | 
			
		||||
                    return false;
 | 
			
		||||
                });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								js/util.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								js/util.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -293,11 +293,19 @@ class Action extends HTMLOutputter // lawsuit
 | 
			
		||||
    {
 | 
			
		||||
        if (Event::handle('StartShowScripts', array($this))) {
 | 
			
		||||
            if (Event::handle('StartShowJQueryScripts', array($this))) {
 | 
			
		||||
                $this->script('jquery.min.js');
 | 
			
		||||
                $this->script('jquery.form.min.js');
 | 
			
		||||
                $this->script('jquery.cookie.min.js');
 | 
			
		||||
                $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.min.js').'"); }');
 | 
			
		||||
                $this->script('jquery.joverlay.min.js');
 | 
			
		||||
                if (common_config('site', 'minify')) {
 | 
			
		||||
                    $this->script('jquery.min.js');
 | 
			
		||||
                    $this->script('jquery.form.min.js');
 | 
			
		||||
                    $this->script('jquery.cookie.min.js');
 | 
			
		||||
                    $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.min.js').'"); }');
 | 
			
		||||
                    $this->script('jquery.joverlay.min.js');
 | 
			
		||||
                } else {
 | 
			
		||||
                    $this->script('jquery.js');
 | 
			
		||||
                    $this->script('jquery.form.js');
 | 
			
		||||
                    $this->script('jquery.cookie.js');
 | 
			
		||||
                    $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.js').'"); }');
 | 
			
		||||
                    $this->script('jquery.joverlay.js');
 | 
			
		||||
                }
 | 
			
		||||
                Event::handle('EndShowJQueryScripts', array($this));
 | 
			
		||||
            }
 | 
			
		||||
            if (Event::handle('StartShowStatusNetScripts', array($this)) &&
 | 
			
		||||
 
 | 
			
		||||
@@ -533,91 +533,95 @@ class ActivityObject
 | 
			
		||||
			$xo->elementStart($tag);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
        $xo->element('activity:object-type', null, $this->type);
 | 
			
		||||
        if (Event::handle('StartActivityObjectOutputAtom', array($this, $xo))) {
 | 
			
		||||
            $xo->element('activity:object-type', null, $this->type);
 | 
			
		||||
 | 
			
		||||
        // <author> uses URI
 | 
			
		||||
            // <author> uses URI
 | 
			
		||||
 | 
			
		||||
        if ($tag == 'author') {
 | 
			
		||||
            $xo->element(self::URI, null, $this->id);
 | 
			
		||||
        } else {
 | 
			
		||||
            $xo->element(self::ID, null, $this->id);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->title)) {
 | 
			
		||||
            $name = common_xml_safe_str($this->title);
 | 
			
		||||
            if ($tag == 'author') {
 | 
			
		||||
                // XXX: Backward compatibility hack -- atom:name should contain
 | 
			
		||||
                // full name here, instead of nickname, i.e.: $name. Change
 | 
			
		||||
                // this in the next version.
 | 
			
		||||
                $xo->element(self::NAME, null, $this->poco->preferredUsername);
 | 
			
		||||
                $xo->element(self::URI, null, $this->id);
 | 
			
		||||
            } else {
 | 
			
		||||
                $xo->element(self::TITLE, null, $name);
 | 
			
		||||
                $xo->element(self::ID, null, $this->id);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->summary)) {
 | 
			
		||||
            $xo->element(
 | 
			
		||||
                self::SUMMARY,
 | 
			
		||||
                null,
 | 
			
		||||
                common_xml_safe_str($this->summary)
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
            if (!empty($this->title)) {
 | 
			
		||||
                $name = common_xml_safe_str($this->title);
 | 
			
		||||
                if ($tag == 'author') {
 | 
			
		||||
                    // XXX: Backward compatibility hack -- atom:name should contain
 | 
			
		||||
                    // full name here, instead of nickname, i.e.: $name. Change
 | 
			
		||||
                    // this in the next version.
 | 
			
		||||
                    $xo->element(self::NAME, null, $this->poco->preferredUsername);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $xo->element(self::TITLE, null, $name);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->content)) {
 | 
			
		||||
            // XXX: assuming HTML content here
 | 
			
		||||
            $xo->element(
 | 
			
		||||
                ActivityUtils::CONTENT,
 | 
			
		||||
                array('type' => 'html'),
 | 
			
		||||
                common_xml_safe_str($this->content)
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->link)) {
 | 
			
		||||
            $xo->element(
 | 
			
		||||
                'link',
 | 
			
		||||
                array(
 | 
			
		||||
                    'rel' => 'alternate',
 | 
			
		||||
                    'type' => 'text/html',
 | 
			
		||||
                    'href' => $this->link
 | 
			
		||||
                ),
 | 
			
		||||
                null
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($this->type == ActivityObject::PERSON
 | 
			
		||||
            || $this->type == ActivityObject::GROUP) {
 | 
			
		||||
 | 
			
		||||
            foreach ($this->avatarLinks as $avatar) {
 | 
			
		||||
            if (!empty($this->summary)) {
 | 
			
		||||
                $xo->element(
 | 
			
		||||
                    'link', array(
 | 
			
		||||
                        'rel'  => 'avatar',
 | 
			
		||||
                        'type'         => $avatar->type,
 | 
			
		||||
                        'media:width'  => $avatar->width,
 | 
			
		||||
                        'media:height' => $avatar->height,
 | 
			
		||||
                        'href' => $avatar->url
 | 
			
		||||
                    self::SUMMARY,
 | 
			
		||||
                    null,
 | 
			
		||||
                    common_xml_safe_str($this->summary)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!empty($this->content)) {
 | 
			
		||||
                // XXX: assuming HTML content here
 | 
			
		||||
                $xo->element(
 | 
			
		||||
                    ActivityUtils::CONTENT,
 | 
			
		||||
                    array('type' => 'html'),
 | 
			
		||||
                    common_xml_safe_str($this->content)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!empty($this->link)) {
 | 
			
		||||
                $xo->element(
 | 
			
		||||
                    'link',
 | 
			
		||||
                    array(
 | 
			
		||||
                        'rel' => 'alternate',
 | 
			
		||||
                        'type' => 'text/html',
 | 
			
		||||
                        'href' => $this->link
 | 
			
		||||
                    ),
 | 
			
		||||
                    null
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->geopoint)) {
 | 
			
		||||
            $xo->element(
 | 
			
		||||
                'georss:point',
 | 
			
		||||
                null,
 | 
			
		||||
                $this->geopoint
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
            if ($this->type == ActivityObject::PERSON
 | 
			
		||||
                || $this->type == ActivityObject::GROUP) {
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->poco)) {
 | 
			
		||||
            $this->poco->outputTo($xo);
 | 
			
		||||
        }
 | 
			
		||||
                foreach ($this->avatarLinks as $avatar) {
 | 
			
		||||
                    $xo->element(
 | 
			
		||||
                        'link', array(
 | 
			
		||||
                            'rel'  => 'avatar',
 | 
			
		||||
                            'type'         => $avatar->type,
 | 
			
		||||
                            'media:width'  => $avatar->width,
 | 
			
		||||
                            'media:height' => $avatar->height,
 | 
			
		||||
                            'href' => $avatar->url
 | 
			
		||||
                        ),
 | 
			
		||||
                        null
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        // @fixme there's no way here to make a tree; elements can only contain plaintext
 | 
			
		||||
        // @fixme these may collide with JSON extensions
 | 
			
		||||
        foreach ($this->extra as $el) {
 | 
			
		||||
            list($extraTag, $attrs, $content) = $el;
 | 
			
		||||
            $xo->element($extraTag, $attrs, $content);
 | 
			
		||||
            if (!empty($this->geopoint)) {
 | 
			
		||||
                $xo->element(
 | 
			
		||||
                    'georss:point',
 | 
			
		||||
                    null,
 | 
			
		||||
                    $this->geopoint
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!empty($this->poco)) {
 | 
			
		||||
                $this->poco->outputTo($xo);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // @fixme there's no way here to make a tree; elements can only contain plaintext
 | 
			
		||||
            // @fixme these may collide with JSON extensions
 | 
			
		||||
            foreach ($this->extra as $el) {
 | 
			
		||||
                list($extraTag, $attrs, $content) = $el;
 | 
			
		||||
                $xo->element($extraTag, $attrs, $content);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Event::handle('EndActivityObjectOutputAtom', array($this, $xo));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		if (!empty($tag)) {
 | 
			
		||||
@@ -647,94 +651,96 @@ class ActivityObject
 | 
			
		||||
    {
 | 
			
		||||
        $object = array();
 | 
			
		||||
 | 
			
		||||
        // XXX: attachedObjects are added by Activity
 | 
			
		||||
        if (Event::handle('StartActivityObjectOutputJson', array($this, &$object))) {
 | 
			
		||||
            // XXX: attachedObjects are added by Activity
 | 
			
		||||
 | 
			
		||||
        // displayName
 | 
			
		||||
        $object['displayName'] = $this->title;
 | 
			
		||||
            // displayName
 | 
			
		||||
            $object['displayName'] = $this->title;
 | 
			
		||||
 | 
			
		||||
        // TODO: downstreamDuplicates
 | 
			
		||||
            // TODO: downstreamDuplicates
 | 
			
		||||
 | 
			
		||||
        // embedCode (used for video)
 | 
			
		||||
            // embedCode (used for video)
 | 
			
		||||
 | 
			
		||||
        // id
 | 
			
		||||
        //
 | 
			
		||||
        // XXX: Should we use URL here? or a crazy tag URI?
 | 
			
		||||
        $object['id'] = $this->id;
 | 
			
		||||
            // id
 | 
			
		||||
            //
 | 
			
		||||
            // XXX: Should we use URL here? or a crazy tag URI?
 | 
			
		||||
            $object['id'] = $this->id;
 | 
			
		||||
 | 
			
		||||
        if ($this->type == ActivityObject::PERSON
 | 
			
		||||
            || $this->type == ActivityObject::GROUP) {
 | 
			
		||||
            if ($this->type == ActivityObject::PERSON
 | 
			
		||||
                || $this->type == ActivityObject::GROUP) {
 | 
			
		||||
 | 
			
		||||
            // XXX: Not sure what the best avatar is to use for the
 | 
			
		||||
            // author's "image". For now, I'm using the large size.
 | 
			
		||||
                // XXX: Not sure what the best avatar is to use for the
 | 
			
		||||
                // author's "image". For now, I'm using the large size.
 | 
			
		||||
 | 
			
		||||
            $avatarLarge      = null;
 | 
			
		||||
            $avatarMediaLinks = array();
 | 
			
		||||
                $avatarLarge      = null;
 | 
			
		||||
                $avatarMediaLinks = array();
 | 
			
		||||
 | 
			
		||||
            foreach ($this->avatarLinks as $a) {
 | 
			
		||||
                foreach ($this->avatarLinks as $a) {
 | 
			
		||||
 | 
			
		||||
                // Make a MediaLink for every other Avatar
 | 
			
		||||
                $avatar = new ActivityStreamsMediaLink(
 | 
			
		||||
                    $a->url,
 | 
			
		||||
                    $a->width,
 | 
			
		||||
                    $a->height,
 | 
			
		||||
                    $a->type,
 | 
			
		||||
                    'avatar'
 | 
			
		||||
                );
 | 
			
		||||
                    // Make a MediaLink for every other Avatar
 | 
			
		||||
                    $avatar = new ActivityStreamsMediaLink(
 | 
			
		||||
                        $a->url,
 | 
			
		||||
                        $a->width,
 | 
			
		||||
                        $a->height,
 | 
			
		||||
                        $a->type,
 | 
			
		||||
                        'avatar'
 | 
			
		||||
                    );
 | 
			
		||||
 | 
			
		||||
                // Find the big avatar to use as the "image"
 | 
			
		||||
                if ($a->height == AVATAR_PROFILE_SIZE) {
 | 
			
		||||
                    $imgLink = $avatar;
 | 
			
		||||
                    // Find the big avatar to use as the "image"
 | 
			
		||||
                    if ($a->height == AVATAR_PROFILE_SIZE) {
 | 
			
		||||
                        $imgLink = $avatar;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    $avatarMediaLinks[] = $avatar->asArray();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $avatarMediaLinks[] = $avatar->asArray();
 | 
			
		||||
                $object['avatarLinks'] = $avatarMediaLinks; // extension
 | 
			
		||||
 | 
			
		||||
                // image
 | 
			
		||||
                $object['image']  = $imgLink->asArray();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $object['avatarLinks'] = $avatarMediaLinks; // extension
 | 
			
		||||
            // objectType
 | 
			
		||||
            //
 | 
			
		||||
            // We can probably use the whole schema URL here but probably the
 | 
			
		||||
            // relative simple name is easier to parse
 | 
			
		||||
            // @fixme this breaks extension URIs
 | 
			
		||||
            $object['type'] = substr($this->type, strrpos($this->type, '/') + 1);
 | 
			
		||||
 | 
			
		||||
            // image
 | 
			
		||||
            $object['image']  = $imgLink->asArray();
 | 
			
		||||
            // summary
 | 
			
		||||
            $object['summary'] = $this->summary;
 | 
			
		||||
 | 
			
		||||
            // TODO: upstreamDuplicates
 | 
			
		||||
 | 
			
		||||
            // url (XXX: need to put the right thing here...)
 | 
			
		||||
            $object['url'] = $this->id;
 | 
			
		||||
 | 
			
		||||
            /* Extensions */
 | 
			
		||||
            // @fixme these may collide with XML extensions
 | 
			
		||||
            // @fixme multiple tags of same name will overwrite each other
 | 
			
		||||
            // @fixme text content from XML extensions will be lost
 | 
			
		||||
            foreach ($this->extra as $e) {
 | 
			
		||||
                list($objectName, $props, $txt) = $e;
 | 
			
		||||
                $object[$objectName] = $props;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // GeoJSON
 | 
			
		||||
 | 
			
		||||
            if (!empty($this->geopoint)) {
 | 
			
		||||
 | 
			
		||||
                list($lat, $long) = explode(' ', $this->geopoint);
 | 
			
		||||
 | 
			
		||||
                $object['geopoint'] = array(
 | 
			
		||||
                    'type'        => 'Point',
 | 
			
		||||
                    'coordinates' => array($lat, $long)
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!empty($this->poco)) {
 | 
			
		||||
                $object['contact'] = $this->poco->asArray();
 | 
			
		||||
            }
 | 
			
		||||
            Event::handle('EndActivityObjectOutputJson', array($this, &$object));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // objectType
 | 
			
		||||
        //
 | 
			
		||||
        // We can probably use the whole schema URL here but probably the
 | 
			
		||||
        // relative simple name is easier to parse
 | 
			
		||||
        // @fixme this breaks extension URIs
 | 
			
		||||
        $object['type'] = substr($this->type, strrpos($this->type, '/') + 1);
 | 
			
		||||
 | 
			
		||||
        // summary
 | 
			
		||||
        $object['summary'] = $this->summary;
 | 
			
		||||
 | 
			
		||||
        // TODO: upstreamDuplicates
 | 
			
		||||
 | 
			
		||||
        // url (XXX: need to put the right thing here...)
 | 
			
		||||
        $object['url'] = $this->id;
 | 
			
		||||
 | 
			
		||||
        /* Extensions */
 | 
			
		||||
        // @fixme these may collide with XML extensions
 | 
			
		||||
        // @fixme multiple tags of same name will overwrite each other
 | 
			
		||||
        // @fixme text content from XML extensions will be lost
 | 
			
		||||
        foreach ($this->extra as $e) {
 | 
			
		||||
            list($objectName, $props, $txt) = $e;
 | 
			
		||||
            $object[$objectName] = $props;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // GeoJSON
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->geopoint)) {
 | 
			
		||||
 | 
			
		||||
            list($lat, $long) = explode(' ', $this->geopoint);
 | 
			
		||||
 | 
			
		||||
            $object['geopoint'] = array(
 | 
			
		||||
                'type'        => 'Point',
 | 
			
		||||
                'coordinates' => array($lat, $long)
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->poco)) {
 | 
			
		||||
            $object['contact'] = $this->poco->asArray();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return array_filter($object);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -212,6 +212,44 @@ abstract class MicroAppPlugin extends Plugin
 | 
			
		||||
                in_array($activity->objects[0]->type, $types));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when generating Atom XML ActivityStreams output from an
 | 
			
		||||
     * ActivityObject belonging to this plugin. Gives the plugin
 | 
			
		||||
     * a chance to add custom output.
 | 
			
		||||
     *
 | 
			
		||||
     * Note that you can only add output of additional XML elements,
 | 
			
		||||
     * not change existing stuff here.
 | 
			
		||||
     *
 | 
			
		||||
     * If output is already handled by the base Activity classes,
 | 
			
		||||
     * you can leave this base implementation as a no-op.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ActivityObject $obj
 | 
			
		||||
     * @param XMLOutputter $out to add elements at end of object
 | 
			
		||||
     */
 | 
			
		||||
    function activityObjectOutputAtom(ActivityObject $obj, XMLOutputter $out)
 | 
			
		||||
    {
 | 
			
		||||
        // default is a no-op
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when generating JSON ActivityStreams output from an
 | 
			
		||||
     * ActivityObject belonging to this plugin. Gives the plugin
 | 
			
		||||
     * a chance to add custom output.
 | 
			
		||||
     *
 | 
			
		||||
     * Modify the array contents to your heart's content, and it'll
 | 
			
		||||
     * all get serialized out as JSON.
 | 
			
		||||
     *
 | 
			
		||||
     * If output is already handled by the base Activity classes,
 | 
			
		||||
     * you can leave this base implementation as a no-op.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ActivityObject $obj
 | 
			
		||||
     * @param array &$out JSON-targeted array which can be modified
 | 
			
		||||
     */
 | 
			
		||||
    public function activityObjectOutputJson(ActivityObject $obj, array &$out)
 | 
			
		||||
    {
 | 
			
		||||
        // default is a no-op
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * When a notice is deleted, delete the related objects
 | 
			
		||||
     * by calling the overridable $this->deleteRelated().
 | 
			
		||||
@@ -439,6 +477,46 @@ abstract class MicroAppPlugin extends Plugin
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Event handler gives the plugin a chance to add custom
 | 
			
		||||
     * Atom XML ActivityStreams output from a previously filled-out
 | 
			
		||||
     * ActivityObject.
 | 
			
		||||
     *
 | 
			
		||||
     * The atomOutput method is called if it's one of
 | 
			
		||||
     * our matching types.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ActivityObject $obj
 | 
			
		||||
     * @param XMLOutputter $out to add elements at end of object
 | 
			
		||||
     * @return boolean hook return value
 | 
			
		||||
     */
 | 
			
		||||
    function onEndActivityObjectOutputAtom(ActivityObject $obj, XMLOutputter $out)
 | 
			
		||||
    {
 | 
			
		||||
        if (in_array($obj->type, $this->types())) {
 | 
			
		||||
            $this->activityObjectOutputAtom($obj, $out);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Event handler gives the plugin a chance to add custom
 | 
			
		||||
     * JSON ActivityStreams output from a previously filled-out
 | 
			
		||||
     * ActivityObject.
 | 
			
		||||
     *
 | 
			
		||||
     * The activityObjectOutputJson method is called if it's one of
 | 
			
		||||
     * our matching types.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ActivityObject $obj
 | 
			
		||||
     * @param array &$out JSON-targeted array which can be modified
 | 
			
		||||
     * @return boolean hook return value
 | 
			
		||||
     */
 | 
			
		||||
    function onEndActivityObjectOutputJson(ActivityObject $obj, array &$out)
 | 
			
		||||
    {
 | 
			
		||||
        if (in_array($obj->type, $this->types())) {
 | 
			
		||||
            $this->activityObjectOutputJson($obj, &$out);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function onStartShowEntryForms(&$tabs)
 | 
			
		||||
    {
 | 
			
		||||
        $tabs[$this->tag()] = $this->appTitle();
 | 
			
		||||
 
 | 
			
		||||
@@ -63,6 +63,9 @@ class PersonalGroupNav extends Menu
 | 
			
		||||
        $nickname     = $user->nickname;
 | 
			
		||||
        $name         = $user_profile->getBestName();
 | 
			
		||||
 | 
			
		||||
        $action = $this->actionName;
 | 
			
		||||
        $mine = ($this->action->arg('nickname') == $nickname); // @fixme kinda vague
 | 
			
		||||
 | 
			
		||||
        $this->out->elementStart('ul', array('class' => 'nav'));
 | 
			
		||||
 | 
			
		||||
        if (Event::handle('StartPersonalGroupNav', array($this))) {
 | 
			
		||||
@@ -70,23 +73,23 @@ class PersonalGroupNav extends Menu
 | 
			
		||||
                                                               $nickname)),
 | 
			
		||||
                                 _('Home'),
 | 
			
		||||
                                 sprintf(_('%s and friends'), $name),
 | 
			
		||||
                                 $this->action == 'all', 'nav_timeline_personal');
 | 
			
		||||
                                 $mine && $action =='all', 'nav_timeline_personal');
 | 
			
		||||
            $this->out->menuItem(common_local_url('showstream', array('nickname' =>
 | 
			
		||||
                                                                      $nickname)),
 | 
			
		||||
                                 _('Profile'),
 | 
			
		||||
                                 _('Your profile'),
 | 
			
		||||
                                 $this->action == 'showstream',
 | 
			
		||||
                                 $mine && $action =='showstream',
 | 
			
		||||
                                 'nav_profile');
 | 
			
		||||
            $this->out->menuItem(common_local_url('replies', array('nickname' =>
 | 
			
		||||
                                                                   $nickname)),
 | 
			
		||||
                                 _('Replies'),
 | 
			
		||||
                                 sprintf(_('Replies to %s'), $name),
 | 
			
		||||
                                 $this->action == 'replies', 'nav_timeline_replies');
 | 
			
		||||
                                 $mine && $action =='replies', 'nav_timeline_replies');
 | 
			
		||||
            $this->out->menuItem(common_local_url('showfavorites', array('nickname' =>
 | 
			
		||||
                                                                         $nickname)),
 | 
			
		||||
                                 _('Favorites'),
 | 
			
		||||
                                 sprintf(_('%s\'s favorite notices'), ($user_profile) ? $name : _('User')),
 | 
			
		||||
                                 $this->action == 'showfavorites', 'nav_timeline_favorites');
 | 
			
		||||
                                 $mine && $action =='showfavorites', 'nav_timeline_favorites');
 | 
			
		||||
 | 
			
		||||
            $cur = common_current_user();
 | 
			
		||||
 | 
			
		||||
@@ -97,7 +100,7 @@ class PersonalGroupNav extends Menu
 | 
			
		||||
                                                                     $nickname)),
 | 
			
		||||
                                     _('Messages'),
 | 
			
		||||
                                     _('Your incoming messages'),
 | 
			
		||||
                                     $this->action == 'inbox');
 | 
			
		||||
                                     $mine && $action =='inbox');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Event::handle('EndPersonalGroupNav', array($this));
 | 
			
		||||
 
 | 
			
		||||
@@ -168,7 +168,5 @@ E_O_T
 | 
			
		||||
        $this->elementStart('div', 'help instructions');
 | 
			
		||||
        $this->raw(common_markup_to_html($message));
 | 
			
		||||
        $this->elementEnd('div');
 | 
			
		||||
 | 
			
		||||
        $this->elementEnd('div');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -191,6 +191,12 @@ class ThreadedNoticeListItem extends NoticeListItem
 | 
			
		||||
                    $item = new ThreadedNoticeListSubItem($notice, $this->out);
 | 
			
		||||
                    $item->show();
 | 
			
		||||
                }
 | 
			
		||||
                // @fixme do a proper can-post check that's consistent
 | 
			
		||||
                // with the JS side
 | 
			
		||||
                if (common_current_user()) {
 | 
			
		||||
                    $item = new ThreadedNoticeListReplyItem($notice, $this->out);
 | 
			
		||||
                    $item->show();
 | 
			
		||||
                }
 | 
			
		||||
                $this->out->elementEnd('ul');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -253,10 +259,7 @@ class ThreadedNoticeListMoreItem extends NoticeListItem
 | 
			
		||||
 | 
			
		||||
    function showStart()
 | 
			
		||||
    {
 | 
			
		||||
        if (Event::handle('StartOpenNoticeListItemElement', array($this))) {
 | 
			
		||||
            $id = (empty($this->repeat)) ? $this->notice->id : $this->repeat->id;
 | 
			
		||||
            $this->out->elementStart('li', array('class' => 'notice-reply-comments'));
 | 
			
		||||
        }
 | 
			
		||||
        $this->out->elementStart('li', array('class' => 'notice-reply-comments'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function showMiniForm()
 | 
			
		||||
@@ -270,21 +273,47 @@ class ThreadedNoticeListMoreItem extends NoticeListItem
 | 
			
		||||
        $msg = sprintf(_m('Show %d reply', 'Show all %d replies', $n), $n);
 | 
			
		||||
 | 
			
		||||
        $this->out->element('a', array('href' => $url), $msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
        // @fixme replace this with an ajax-friendly form pair?
 | 
			
		||||
        /*
 | 
			
		||||
        $this->out->elementStart('form',
 | 
			
		||||
                                 array('id' => $id,
 | 
			
		||||
                                       'class' => 'replyform',
 | 
			
		||||
                                       'method' => 'post',
 | 
			
		||||
                                       'action' => $url));
 | 
			
		||||
        $this->out->hidden('token', common_session_token());
 | 
			
		||||
        $this->out->hidden("$id-inreplyto", $replyToId, "inreplyto");
 | 
			
		||||
        $this->out->element('textarea', array('name' => 'status_textarea'));
 | 
			
		||||
        $this->out->elementStart('div', array('class' => 'controls'));
 | 
			
		||||
        $this->out->submit("$id-submit", _m('Send reply'));
 | 
			
		||||
        $this->out->elementEnd('div');
 | 
			
		||||
        $this->out->elementEnd('form');
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Placeholder for reply form...
 | 
			
		||||
 * Same as get added at runtime via SN.U.NoticeInlineReplyPlaceholder
 | 
			
		||||
 */
 | 
			
		||||
class ThreadedNoticeListReplyItem extends NoticeListItem
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * recipe function for displaying a single notice.
 | 
			
		||||
     *
 | 
			
		||||
     * This uses all the other methods to correctly display a notice. Override
 | 
			
		||||
     * it or one of the others to fine-tune the output.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function show()
 | 
			
		||||
    {
 | 
			
		||||
        $this->showStart();
 | 
			
		||||
        $this->showMiniForm();
 | 
			
		||||
        $this->showEnd();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * start a single notice.
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function showStart()
 | 
			
		||||
    {
 | 
			
		||||
        $this->out->elementStart('li', array('class' => 'notice-reply-placeholder'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function showMiniForm()
 | 
			
		||||
    {
 | 
			
		||||
        $this->out->element('input', array('class' => 'placeholder',
 | 
			
		||||
                                           'value' => _('Write a reply...')));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -48,8 +48,8 @@ class PollPlugin extends MicroAppPlugin
 | 
			
		||||
    const VERSION         = '0.1';
 | 
			
		||||
 | 
			
		||||
    // @fixme which domain should we use for these namespaces?
 | 
			
		||||
    const POLL_OBJECT          = 'http://apinamespace.org/activitystreams/object/poll';
 | 
			
		||||
    const POLL_RESPONSE_OBJECT = 'http://apinamespace.org/activitystreams/object/poll-response';
 | 
			
		||||
    const POLL_OBJECT          = 'http://activityschema.org/object/poll';
 | 
			
		||||
    const POLL_RESPONSE_OBJECT = 'http://activityschema.org/object/poll-response';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Database schema setup
 | 
			
		||||
@@ -203,26 +203,22 @@ class PollPlugin extends MicroAppPlugin
 | 
			
		||||
            $pollElements = $activity->entry->getElementsByTagNameNS(self::POLL_OBJECT, 'poll');
 | 
			
		||||
            $responseElements = $activity->entry->getElementsByTagNameNS(self::POLL_OBJECT, 'response');
 | 
			
		||||
            if ($pollElements->length) {
 | 
			
		||||
                $data = $pollElements->item(0);
 | 
			
		||||
                $question = $data->getAttribute('question');
 | 
			
		||||
                $question = '';
 | 
			
		||||
                $opts = array();
 | 
			
		||||
                foreach ($data->attributes as $node) {
 | 
			
		||||
                    $name = $node->nodeName;
 | 
			
		||||
                    if (substr($name, 0, 6) == 'option') {
 | 
			
		||||
                        $n = intval(substr($name, 6));
 | 
			
		||||
                        if ($n > 0) {
 | 
			
		||||
                            $opts[$n - 1] = $node->nodeValue;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                $data = $pollElements->item(0);
 | 
			
		||||
                foreach ($data->getElementsByTagNameNS(self::POLL_OBJECT, 'question') as $node) {
 | 
			
		||||
                    $question = $node->textContent;
 | 
			
		||||
                }
 | 
			
		||||
                foreach ($data->getElementsByTagNameNS(self::POLL_OBJECT, 'option') as $node) {
 | 
			
		||||
                    $opts[] = $node->textContent;
 | 
			
		||||
                }
 | 
			
		||||
                common_log(LOG_DEBUG, "YYY question: $question");
 | 
			
		||||
                common_log(LOG_DEBUG, "YYY opts: " . var_export($opts, true));
 | 
			
		||||
                try {
 | 
			
		||||
                    $notice = Poll::saveNew($profile, $question, $opts, $options);
 | 
			
		||||
                    common_log(LOG_DEBUG, "YYY ok: " . $notice->id);
 | 
			
		||||
                    common_log(LOG_DEBUG, "Saved Poll from ActivityStream data ok: notice id " . $notice->id);
 | 
			
		||||
                    return $notice;
 | 
			
		||||
                } catch (Exception $e) {
 | 
			
		||||
                    common_log(LOG_DEBUG, "YYY fail: " . $e->getMessage());
 | 
			
		||||
                    common_log(LOG_DEBUG, "Poll save from ActivityStream data failed: " . $e->getMessage());
 | 
			
		||||
                }
 | 
			
		||||
            } else if ($responseElements->length) {
 | 
			
		||||
                $data = $responseElements->item(0);
 | 
			
		||||
@@ -240,10 +236,10 @@ class PollPlugin extends MicroAppPlugin
 | 
			
		||||
                }
 | 
			
		||||
                try {
 | 
			
		||||
                    $notice = Poll_response::saveNew($profile, $poll, $selection, $options);
 | 
			
		||||
                    common_log(LOG_DEBUG, "YYY response ok: " . $notice->id);
 | 
			
		||||
                    common_log(LOG_DEBUG, "Saved Poll_response ok, notice id: " . $notice->id);
 | 
			
		||||
                    return $notice;
 | 
			
		||||
                } catch (Exception $e) {
 | 
			
		||||
                    common_log(LOG_DEBUG, "YYY response fail: " . $e->getMessage());
 | 
			
		||||
                    common_log(LOG_DEBUG, "Poll response  save fail: " . $e->getMessage());
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                common_log(LOG_DEBUG, "YYY no poll data");
 | 
			
		||||
@@ -277,33 +273,15 @@ class PollPlugin extends MicroAppPlugin
 | 
			
		||||
        $object->link    = $notice->bestUrl();
 | 
			
		||||
 | 
			
		||||
        $response = Poll_response::getByNotice($notice);
 | 
			
		||||
        if (!$response) {
 | 
			
		||||
            common_log(LOG_DEBUG, "QQQ notice uri: $notice->uri");
 | 
			
		||||
        } else {
 | 
			
		||||
        if ($response) {
 | 
			
		||||
            $poll = $response->getPoll();
 | 
			
		||||
            /**
 | 
			
		||||
             * For the moment, using a kind of icky-looking schema that happens to
 | 
			
		||||
             * work with out code for generating both Atom and JSON forms, though
 | 
			
		||||
             * I don't like it:
 | 
			
		||||
             *
 | 
			
		||||
             * <poll:response xmlns:poll="http://apinamespace.org/activitystreams/object/poll"
 | 
			
		||||
             *                poll="http://..../poll/...."
 | 
			
		||||
             *                selection="3" />
 | 
			
		||||
             *
 | 
			
		||||
             * "poll:response": {
 | 
			
		||||
             *     "xmlns:poll": http://apinamespace.org/activitystreams/object/poll
 | 
			
		||||
             *     "uri": "http://..../poll/...."
 | 
			
		||||
             *     "selection": 3
 | 
			
		||||
             * }
 | 
			
		||||
             *
 | 
			
		||||
             */
 | 
			
		||||
            // @fixme there's no way to specify an XML node tree here, like <poll><option/><option/></poll>
 | 
			
		||||
            // @fixme there's no way to specify a JSON array or multi-level tree unless you break the XML attribs
 | 
			
		||||
            // @fixme XML node contents don't get shown in JSON
 | 
			
		||||
            $data = array('xmlns:poll' => self::POLL_OBJECT,
 | 
			
		||||
                          'poll'       => $poll->uri,
 | 
			
		||||
                          'selection'  => intval($response->selection));
 | 
			
		||||
            $object->extra[] = array('poll:response', $data, '');
 | 
			
		||||
            if ($poll) {
 | 
			
		||||
                // Stash data to be formatted later by
 | 
			
		||||
                // $this->activityObjectOutputAtom() or
 | 
			
		||||
                // $this->activityObjectOutputJson()...
 | 
			
		||||
                $object->pollSelection = intval($response->selection);
 | 
			
		||||
                $object->pollUri = $poll->uri;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return $object;
 | 
			
		||||
    }
 | 
			
		||||
@@ -318,41 +296,112 @@ class PollPlugin extends MicroAppPlugin
 | 
			
		||||
        $object->link    = $notice->bestUrl();
 | 
			
		||||
 | 
			
		||||
        $poll = Poll::getByNotice($notice);
 | 
			
		||||
        /**
 | 
			
		||||
         * Adding the poll-specific data. There's no standard in AS for polls,
 | 
			
		||||
         * so we're making stuff up.
 | 
			
		||||
         *
 | 
			
		||||
         * For the moment, using a kind of icky-looking schema that happens to
 | 
			
		||||
         * work with out code for generating both Atom and JSON forms, though
 | 
			
		||||
         * I don't like it:
 | 
			
		||||
         *
 | 
			
		||||
         * <poll:data xmlns:poll="http://apinamespace.org/activitystreams/object/poll"
 | 
			
		||||
         *            question="Who wants a poll question?"
 | 
			
		||||
         *            option1="Option one"
 | 
			
		||||
         *            option2="Option two"
 | 
			
		||||
         *            option3="Option three"></poll:data>
 | 
			
		||||
         *
 | 
			
		||||
         * "poll:response": {
 | 
			
		||||
         *     "xmlns:poll": http://apinamespace.org/activitystreams/object/poll
 | 
			
		||||
         *     "question": "Who wants a poll question?"
 | 
			
		||||
         *     "option1": "Option one"
 | 
			
		||||
         *     "option2": "Option two"
 | 
			
		||||
         *     "option3": "Option three"
 | 
			
		||||
         * }
 | 
			
		||||
         *
 | 
			
		||||
         */
 | 
			
		||||
        // @fixme there's no way to specify an XML node tree here, like <poll><option/><option/></poll>
 | 
			
		||||
        // @fixme there's no way to specify a JSON array or multi-level tree unless you break the XML attribs
 | 
			
		||||
        // @fixme XML node contents don't get shown in JSON
 | 
			
		||||
        $data = array('xmlns:poll' => self::POLL_OBJECT,
 | 
			
		||||
                      'question'   => $poll->question);
 | 
			
		||||
        foreach ($poll->getOptions() as $i => $opt) {
 | 
			
		||||
            $data['option' . ($i + 1)] = $opt;
 | 
			
		||||
        if ($poll) {
 | 
			
		||||
            // Stash data to be formatted later by
 | 
			
		||||
            // $this->activityObjectOutputAtom() or
 | 
			
		||||
            // $this->activityObjectOutputJson()...
 | 
			
		||||
            $object->pollQuestion = $poll->question;
 | 
			
		||||
            $object->pollOptions = $poll->getOptions();
 | 
			
		||||
        }
 | 
			
		||||
        $object->extra[] = array('poll:poll', $data, '');
 | 
			
		||||
 | 
			
		||||
        return $object;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when generating Atom XML ActivityStreams output from an
 | 
			
		||||
     * ActivityObject belonging to this plugin. Gives the plugin
 | 
			
		||||
     * a chance to add custom output.
 | 
			
		||||
     *
 | 
			
		||||
     * Note that you can only add output of additional XML elements,
 | 
			
		||||
     * not change existing stuff here.
 | 
			
		||||
     *
 | 
			
		||||
     * If output is already handled by the base Activity classes,
 | 
			
		||||
     * you can leave this base implementation as a no-op.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ActivityObject $obj
 | 
			
		||||
     * @param XMLOutputter $out to add elements at end of object
 | 
			
		||||
     */
 | 
			
		||||
    function activityObjectOutputAtom(ActivityObject $obj, XMLOutputter $out)
 | 
			
		||||
    {
 | 
			
		||||
        if (isset($obj->pollQuestion)) {
 | 
			
		||||
            /**
 | 
			
		||||
             * <poll:poll xmlns:poll="http://apinamespace.org/activitystreams/object/poll">
 | 
			
		||||
             *   <poll:question>Who wants a poll question?</poll:question>
 | 
			
		||||
             *   <poll:option>Option one</poll:option>
 | 
			
		||||
             *   <poll:option>Option two</poll:option>
 | 
			
		||||
             *   <poll:option>Option three</poll:option>
 | 
			
		||||
             * </poll:poll>
 | 
			
		||||
             */
 | 
			
		||||
            $data = array('xmlns:poll' => self::POLL_OBJECT);
 | 
			
		||||
            $out->elementStart('poll:poll', $data);
 | 
			
		||||
            $out->element('poll:question', array(), $obj->pollQuestion);
 | 
			
		||||
            foreach ($obj->pollOptions as $opt) {
 | 
			
		||||
                $out->element('poll:option', array(), $opt);
 | 
			
		||||
            }
 | 
			
		||||
            $out->elementEnd('poll:poll');
 | 
			
		||||
        }
 | 
			
		||||
        if (isset($obj->pollSelection)) {
 | 
			
		||||
            /**
 | 
			
		||||
             * <poll:response xmlns:poll="http://apinamespace.org/activitystreams/object/poll">
 | 
			
		||||
             *                poll="http://..../poll/...."
 | 
			
		||||
             *                selection="3" />
 | 
			
		||||
             */
 | 
			
		||||
            $data = array('xmlns:poll' => self::POLL_OBJECT,
 | 
			
		||||
                          'poll'       => $obj->pollUri,
 | 
			
		||||
                          'selection'  => $obj->pollSelection);
 | 
			
		||||
            $out->element('poll:response', $data, '');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when generating JSON ActivityStreams output from an
 | 
			
		||||
     * ActivityObject belonging to this plugin. Gives the plugin
 | 
			
		||||
     * a chance to add custom output.
 | 
			
		||||
     *
 | 
			
		||||
     * Modify the array contents to your heart's content, and it'll
 | 
			
		||||
     * all get serialized out as JSON.
 | 
			
		||||
     *
 | 
			
		||||
     * If output is already handled by the base Activity classes,
 | 
			
		||||
     * you can leave this base implementation as a no-op.
 | 
			
		||||
     *
 | 
			
		||||
     * @param ActivityObject $obj
 | 
			
		||||
     * @param array &$out JSON-targeted array which can be modified
 | 
			
		||||
     */
 | 
			
		||||
    public function activityObjectOutputJson(ActivityObject $obj, array &$out)
 | 
			
		||||
    {
 | 
			
		||||
        common_log(LOG_DEBUG, 'QQQ: ' . var_export($obj, true));
 | 
			
		||||
        if (isset($obj->pollQuestion)) {
 | 
			
		||||
            /**
 | 
			
		||||
             * "poll": {
 | 
			
		||||
             *   "question": "Who wants a poll question?",
 | 
			
		||||
             *   "options": [
 | 
			
		||||
             *     "Option 1",
 | 
			
		||||
             *     "Option 2",
 | 
			
		||||
             *     "Option 3"
 | 
			
		||||
             *   ]
 | 
			
		||||
             * }
 | 
			
		||||
             */
 | 
			
		||||
            $data = array('question' => $obj->pollQuestion,
 | 
			
		||||
                          'options' => array());
 | 
			
		||||
            foreach ($obj->pollOptions as $opt) {
 | 
			
		||||
                $data['options'][] = $opt;
 | 
			
		||||
            }
 | 
			
		||||
            $out['poll'] = $data;
 | 
			
		||||
        }
 | 
			
		||||
        if (isset($obj->pollSelection)) {
 | 
			
		||||
            /**
 | 
			
		||||
             * "pollResponse": {
 | 
			
		||||
             *   "poll": "http://..../poll/....",
 | 
			
		||||
             *   "selection": 3
 | 
			
		||||
             * }
 | 
			
		||||
             */
 | 
			
		||||
            $data = array('poll'       => $obj->pollUri,
 | 
			
		||||
                          'selection'  => $obj->pollSelection);
 | 
			
		||||
            $out['pollResponse'] = $data;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @fixme WARNING WARNING WARNING parent class closes the final div that we
 | 
			
		||||
     * open here, but we probably shouldn't open it here. Check parent class
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user