aboutsummaryrefslogtreecommitdiffstats
path: root/Zotlabs
diff options
context:
space:
mode:
Diffstat (limited to 'Zotlabs')
-rw-r--r--Zotlabs/Lib/Activity.php45
-rw-r--r--Zotlabs/Module/Item.php63
-rw-r--r--Zotlabs/Module/Vote.php129
3 files changed, 231 insertions, 6 deletions
diff --git a/Zotlabs/Lib/Activity.php b/Zotlabs/Lib/Activity.php
index 43315a87f..66b1ee4b8 100644
--- a/Zotlabs/Lib/Activity.php
+++ b/Zotlabs/Lib/Activity.php
@@ -813,6 +813,10 @@ class Activity {
static function activity_mapper($verb) {
+ if ($verb === 'Answer') {
+ return 'Note';
+ }
+
if(strpos($verb,'/') === false) {
return $verb;
}
@@ -932,10 +936,6 @@ class Activity {
static function activity_obj_mapper($obj) {
- if(strpos($obj,'/') === false) {
- return $obj;
- }
-
$objs = [
'http://activitystrea.ms/schema/1.0/note' => 'Note',
'http://activitystrea.ms/schema/1.0/comment' => 'Note',
@@ -956,6 +956,15 @@ class Activity {
call_hooks('activity_obj_mapper',$objs);
+ if ($obj === 'Answer') {
+ return 'Note';
+ }
+
+ if (strpos($obj,'/') === false) {
+ return $obj;
+ }
+
+
if(array_key_exists($obj,$objs)) {
return $objs[$obj];
}
@@ -1644,6 +1653,13 @@ class Activity {
$s['expires'] = datetime_convert('UTC','UTC',$act->obj['expires']);
}
+ if ($act->type === 'Note' && $act->obj['type'] === 'Question' && $act->data['name']) {
+ $s['mid'] = $act->id;
+ $s['parent_mid'] = $act->obj['id'];
+ $s['replyto'] = $act->replyto;
+ $s['verb'] = 'Answer';
+ $content['content'] = EMPTY_STR;
+ }
if(in_array($act->type, [ 'Like', 'Dislike', 'Flag', 'Block', 'Announce', 'Accept', 'Reject', 'TentativeAccept', 'emojiReaction' ])) {
@@ -1711,6 +1727,15 @@ class Activity {
$s['verb'] = self::activity_decode_mapper($act->type);
+ if ($act->type === 'Note' && $act->obj['type'] === 'Question' && $act->data['name'] && ! $content['content']) {
+ $s['verb'] = 'Answer';
+ $s['title'] = purify_html($act->data['name']);
+ }
+
+ // Mastodon does not provide update timestamps when updating poll tallies which means race conditions may occur here.
+ if ($act->type === 'Update' && $act->obj['type'] === 'Question' && $s['edited'] === $s['created']) {
+ $s['edited'] = datetime_convert();
+ }
if($act->type === 'Tombstone' || $act->type === 'Delete' || ($act->type === 'Create' && $act->obj['type'] === 'Tombstone')) {
$s['item_deleted'] = 1;
@@ -1798,6 +1823,18 @@ class Activity {
}
+ if ($act->obj['type'] === 'Question' && in_array($act->type,['Create','Update'])) {
+ if ($act->obj['endTime']) {
+ $s['comments_closed'] = datetime_convert('UTC','UTC', $act->obj['endTime']);
+ }
+ }
+
+ if ($act->obj['closed']) {
+ $s['comments_closed'] = datetime_convert('UTC','UTC', $act->obj['closed']);
+ }
+
+
+
// we will need a hook here to extract magnet links e.g. peertube
// right now just link to the largest mp4 we find that will fit in our
// standard content region
diff --git a/Zotlabs/Module/Item.php b/Zotlabs/Module/Item.php
index 1a25e54df..8b4bbae91 100644
--- a/Zotlabs/Module/Item.php
+++ b/Zotlabs/Module/Item.php
@@ -718,7 +718,14 @@ class Item extends Controller {
// BBCODE alert: the following functions assume bbcode input
// and will require alternatives for alternative content-types (text/html, text/markdown, text/plain, etc.)
// we may need virtual or template classes to implement the possible alternatives
-
+
+ $obj = $this->extract_poll_data($body);
+ if ($obj) {
+ $datarray['obj'] = $obj;
+ $obj_type = 'Question';
+ }
+
+
if(strpos($body,'[/summary]') !== false) {
$match = '';
@@ -1387,5 +1394,57 @@ class Item extends Controller {
return $ret;
}
-
+ function extract_poll_data(&$body) {
+
+ $multiple = false;
+
+ if (strpos($body,'[/question]') === false && strpos($body,'[/answer]') === false) {
+ return false;
+ }
+ if (strpos($body,'[nobb]') !== false) {
+ return false;
+ }
+
+
+ $obj = [];
+ $ptr = [];
+ $matches = null;
+ $obj['type'] = 'Question';
+
+ if (preg_match_all('/\[answer\](.*?)\[\/answer\]/',$body,$matches,PREG_SET_ORDER)) {
+ foreach ($matches as $match) {
+ $ptr[] = [ 'name' => $match[1], 'type' => 'Note', 'replies' => [ 'type' => 'Collection', 'totalItems' => 0 ]];
+ $body = str_replace('[answer]' . $match[1] . '[/answer]', EMPTY_STR, $body);
+ }
+ }
+
+ $matches = null;
+
+ if (preg_match('/\[question\](.*?)\[\/question\]/',$body,$matches)) {
+ $obj['content'] = bbcode($matches[1]);
+ $body = str_replace('[question]' . $matches[1] . '[/question]', $matches[1], $body);
+ $obj['oneOf'] = $ptr;
+ }
+
+ $matches = null;
+
+ if (preg_match('/\[question=multiple\](.*?)\[\/question\]/',$body,$matches)) {
+ $obj['content'] = bbcode($matches[1]);
+ $body = str_replace('[question=multiple]' . $matches[1] . '[/question]', $matches[1], $body);
+ $obj['anyOf'] = $ptr;
+ }
+
+ $matches = null;
+
+ if (preg_match('/\[ends\](.*?)\[\/ends\]',$body,$matches)) {
+ $obj['endTime'] = datetime_convert(date_default_timezone_get(),'UTC', $matches[1],ATOM_TIME);
+ $body = str_replace('[ends]' . $match[1] . '[/ends]', EMPTY_STR, $body);
+ }
+
+ return $obj;
+
+ }
+
+
+
}
diff --git a/Zotlabs/Module/Vote.php b/Zotlabs/Module/Vote.php
new file mode 100644
index 000000000..52d6a4bea
--- /dev/null
+++ b/Zotlabs/Module/Vote.php
@@ -0,0 +1,129 @@
+<?php
+namespace Zotlabs\Module;
+
+use App;
+use Zotlabs\Web\Controller;
+use Zotlabs\Lib\Activity;
+use Zotlabs\Daemon\Master;
+use Zotlabs\Lib\Libsync;
+
+class Vote extends Controller {
+
+ function init() {
+
+ $ret = [ 'success' => false, 'message' => EMPTY_STR ];
+
+ $channel = App::get_channel();
+
+ if (! $channel) {
+ $ret['message'] = t('Permission denied.');
+ json_return_and_die($ret);
+ }
+
+
+ $fetch = null;
+ $id = argv(1);
+ $response = $_REQUEST['answer'];
+
+ if ($id) {
+ $fetch = q("select * from item where id = %d limit 1",
+ intval($id)
+ );
+ }
+
+
+ if ($fetch && $fetch[0]['obj_type'] === 'Question') {
+ $obj = json_decode($fetch[0]['obj'],true);
+
+ }
+ else {
+ $ret['message'] = t('Poll not found.');
+ json_return_and_die($ret);
+ }
+
+ $valid = false;
+
+ if ($obj['oneOf']) {
+ foreach($obj['oneOf'] as $selection) {
+ // logger('selection: ' . $selection);
+ // logger('response: ' . $response);
+ if($selection['name'] && $selection['name'] === $response) {
+ $valid = true;
+ }
+ }
+ }
+
+ $choices = [];
+ if ($obj['anyOf']) {
+ foreach ($obj['anyOf'] as $selection) {
+ $choices[] = $selection['name'];
+ }
+ foreach ($response as $res) {
+ if (! in_array($res,$choices)) {
+ $valid = false;
+ break;
+ }
+ $valid = true;
+ }
+ }
+
+ if (! $valid) {
+ $ret['message'] = t('Invalid response.');
+ json_return_and_die($ret);
+ }
+
+ if (! is_array($response)) {
+ $response = [ $response ];
+ }
+
+ foreach ($response as $res) {
+
+ $item = [];
+
+
+ $item['aid'] = $channel['channel_account_id'];
+ $item['uid'] = $channel['channel_id'];
+ $item['item_origin'] = true;
+ $item['parent'] = $fetch[0]['id'];
+ $item['parent_mid'] = $fetch[0]['mid'];
+ $item['uuid'] = new_uuid();
+ $item['mid'] = z_root() . '/item/' . $item['uuid'];
+ $item['verb'] = 'Answer';
+ $item['title'] = $res;
+ $item['author_xchan'] = $channel['channel_hash'];
+ $item['owner_xchan'] = $fetch[0]['author_xchan'];
+
+ $item['obj'] = $obj;
+ $item['obj_type'] = 'Question';
+
+ $x = item_store($item);
+
+ retain_item($fetch[0]['id']);
+
+ if($x['success']) {
+ $itemid = $x['item_id'];
+ Master::Summon( [ 'Notifier', 'like', $itemid ] );
+ }
+
+ $r = q("select * from item where id = %d",
+ intval($itemid)
+ );
+ if ($r) {
+ xchan_query($r);
+ $sync_item = fetch_post_tags($r);
+ Libsync::build_sync_packet($channel['channel_id'], [ 'item' => [ encode_item($sync_item[0],true) ] ]);
+ }
+ }
+ $ret['success'] = true;
+ $ret['message'] = t('Response submitted. Updates may not appear instantly.');
+ json_return_and_die($ret);
+ }
+}
+
+
+
+
+
+
+
+