diff --git a/src/ContentNation/ActivityPub/Common/APObject.php b/src/ContentNation/ActivityPub/Common/APObject.php new file mode 100644 index 0000000..42cee8d --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/APObject.php @@ -0,0 +1,751 @@ + + */ + private $to = array(); + + // bto + /** + * list of cc ids + * @var array + */ + private $cc = array(); + + // bcc + /** + * media type + * @var string + */ + private $mediaType = ""; + + // duration + + /** + * list of contexts + * @var array> + */ + private $context = []; + + /** + * atom URI + * @var string + */ + private $atomURI = ''; + + /** + * reply to atom URI + * @var ?string + */ + private $replyAtomURI = null; + + // found items + /** + * Content Nation generated unique id + * @var string + */ + private $uuid = ""; + + /** + * sensitive flag + * @var ?bool + */ + private $sensitive = null; + /** + * blur hash + * @var string + */ + private $blurhash = ""; + + /** + * conversation id + * @var string + */ + private $conversation = ''; + + public function __construct(string $type) { + $this->type = $type; + } + + + /** + * set note content + * @param string $content note content + * @return APObject current instance + */ + public function setContent(string $content) : APObject { + $this->content = $content; + return $this; + } + + public function getContent() : string { + return $this->content; + } + + /** + * add context to list + * @param string|array $context new context + */ + final public function addContext($context) : void { + if (!in_array($context, $this->context)) { + $this->context[] = $context; + } + } + /** + * set id + * @param string $id new id + */ + final public function setID(string $id) { + $this->id = $id; + } + + final public function getID() : string { + return $this->id; + } + + /** + * set href + * @param string $href href + */ + public function setHref(string $href) : void { + $this->href = $href; + } + + /** + * set child object + * @param APObject $object + */ + public function setObject($object) : void { + $this->object = $object; + } + /** + * get child object + * @return APObject | false child object + */ + public function getObject() { + return $this->object; + } + + /** + * set type + * @param string $type type + */ + public function setType(string $type) : void { + $this->type = $type; + } + + public function getType() : string { + return $this->type; + } + + /** + * set attachments + * @param APObject[] $attachment + */ + public function setAttachment($attachment) : void { + $this->attachment = $attachment; + } + + public function addAttachment(APObject $attachment) : void { + $this->attachment[] = $attachment; + } + + /** + * get attachments + * @return APObject[] attachments + */ + public function getAttachment() { + return $this->attachment; + } + + public function getAttachmentsAsJson() : string { + if ($this->attachment === []) { + return "{}"; + } + $obj = array(); + foreach($this->attachment as $a) { + $obj[] = $a->toObject(); + } + return json_encode($obj); + } + + + /** + * set attributed to + * @param string $to attribute to + */ + public function setAttributedTo(string $to) : void { + $this->attributedTo = $to; + } + + public function getAttributedTo() : string { + return $this->attributedTo; + } + + /** + * set name + * @param string $name name + */ + public function setName(string $name) : void { + $this->name = $name; + } + + + /** + * add Image + * @param Image $image image to add + */ + public function addImage(Image $image) : void { + $this->image[] = $image; + } + + public function setInReplyTo(string $reply) : void { + $this->inReplyTo = $reply; + } + + public function getInReplyTo() : string { + return $this->inReplyTo ?? ""; + } + + /** + * set published timestamp + * @param int $published published timestamp + */ + public function setPublished(int $published) : void { + $this->published = $published; + } + + public function getPublished() : int { + return $this->published; + } + + /** + * add Tag + * @param Tag $tag tag to add + */ + public function addTag(Tag $tag) : void { + $this->tag[] = $tag; + } + + /** + * set url + * @param string $url URL + */ + public function setURL(string $url) : void { + $this->url = $url; + } + + /** + * get URL + * @return string URL + */ + public function getURL() : string { + return $this->url; + } + + /** + * add to + * @param string $to additional to address + */ + public function addTo(string $to) : void { + $this->to[] = $to; + } + + /** + * get to + * @return array + */ + public function getTo() { + return $this->to; + } + /** + * add cc + * @param string $cc additional cc address + */ + public function addCC(string $cc) : void { + $this->cc[] = $cc; + } + /** + * get cc + * @return array + */ + public function getCC() { + return $this->cc; + } + + public function getMediaType() : string { + return $this->mediaType; + } + /** + * set atom URI + * @param string $uri atom URI + */ + public function setAtomURI(string $uri) : void { + $this->atomURI = $uri; + } + + /** + * set reply atom URI + * @param string $uri reply atom URI + */ + public function setReplyAtomURI(string $uri) : void { + $this->replyAtomURI = $uri; + } + + /** + * set sensitive + * @param bool $sensitive status + */ + public function setSensitive(bool $sensitive) : void { + $this->sensitive = $sensitive; + } + + /** + * set conversation id + * @param string $conversation conversation ID + */ + public function setConversation(string $conversation) : void { + $this->conversation = $conversation; + } + + public function getConversation() : ?string { + return $this->conversation; + } + + /** + * @param array $json input + */ + public function fromJson($json) : bool { + if (!is_array($json)) { + error_log("fromJson called with ".gettype($json). " => ". debug_backtrace()[1]['function'] . " json: " . print_r($json, true)); + return false; + } + if (array_key_exists('id', $json)) { + $this->id = $json['id']; + } + if (array_key_exists('content', $json)) { + $this->content = $json['content']; + } + if (array_key_exists('duration', $json)) { + try { + $this->duration = new \DateInterval($json['duration']); + } catch (\Exception $unused_e) { + error_log("error parsing duration ". $json['duration']); + } + } + if (array_key_exists('height', $json)) { + $this->height = intval($json['height'], 10); + } + if (array_key_exists('href', $json)) { + $this->href = $json['href']; + } + if (array_key_exists('endTime', $json) && $json['endTime'] !== null) { + $this->endTime = $this->parseDateTime($json['endTime']); + } + if (array_key_exists('width', $json)) { + $this->width = intval($json['width'], 10); + } + if (array_key_exists('attachment', $json) && $json['attachment'] !== null) { + $attachment = []; + foreach($json['attachment'] as $a) { + $att = \ContentNation\ActivityPub\Factory::newFromJson($a, ""); + if ($att !== false) { + $attachment[] = $att; + } + } + $this->attachment = $attachment; + } + if (array_key_exists('attributedTo', $json)) { + if (is_array($json['attributedTo']) && array_key_exists(0, $json['attributedTo'])) { + // error_log("attributedTo is array" . print_r($json['attributedTo'], true)); + if (is_array($json['attributedTo'][0])) { + $this->attributedTo = $json['attributedTo'][0]['id']; + } else { + $this->attributedTo = $json['attributedTo'][0]; + } + } else { + $this->attributedTo = $json['attributedTo']; + } + } + if (array_key_exists('name', $json)) { + $this->name = $json['name']; + } + if (array_key_exists('icon',$json)) { + if (array_key_exists('type', $json['icon'])) { + $image = \ContentNation\ActivityPub\Factory::newImage(); + $image->fromJson($json['icon']); + $this->icon[] = $image; + } else { + foreach($json['icon'] as $icon) { + $image = \ContentNation\ActivityPub\Factory::newImage(); + $image->fromJson($icon); + $this->icon[] = $image; + } + } + } + if (array_key_exists('image',$json)) { + $image = \ContentNation\ActivityPub\Factory::newImage(); + $image->fromJson($json['image']); + $this->image[] = $image; + } + if (array_key_exists('inReplyTo', $json)) { + $this->inReplyTo = $json['inReplyTo']; + } + if (array_key_exists('published', $json)) { + $this->published = $this->parseDateTime($json['published']); + } + if (array_key_exists('summary', $json)) { + $this->summary = $json['summary']; + } + if (array_key_exists('tag', $json)) { + require_once("Tag.php"); + $tags = []; + foreach($json['tag'] as $t) { + $tag = new Tag(); + $tag->fromJson($t); + $tags[] = $tag; + } + $this->tag = $tags; + } + if (array_key_exists('updated', $json)) { + $this->updated = $this->parseDateTime($json['updated']); + } + if (array_key_exists('url', $json)) { + $this->url = $json['url']; + } + if (array_key_exists('to', $json)) { + if (is_array($json['to'])) { + foreach($json['to'] as $to) { + $this->to[] = $to; + } + } else { + $this->to[] = $json['to']; + } + } + if (array_key_exists('cc', $json)) { + if (is_array($json['cc'])) { + foreach($json['cc'] as $cc) { + $this->cc[] = $cc; + } + } else { + $this->cc[] = $json['cc']; + } + } + if (array_key_exists('mediaType', $json)) { + $this->mediaType = $json['mediaType']; + } + if (array_key_exists('object', $json)) { + $this->object = \ContentNation\ActivityPub\Factory::newFromJson($json['object'], ""); + } + if (array_key_exists('sensitive', $json)) { + $this->sensitive = $json['sensitive']; + } + if (array_key_exists('blurhash', $json)) { + $this->blurhash = $json['blurhash']; + } + if (array_key_exists('uuid', $json)) { + $this->uuid = $json['uuid']; + } + if (array_key_exists('conversation', $json)) { + $this->conversation = $json['conversation']; + } + return true; + } + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = []; + if (sizeof($this->context) == 1) { + $return['@context'] = array_values($this->context)[0]; + } else if (sizeof($this->context) > 1) { + $c = []; + foreach(array_values($this->context) as $context) { + $c[] = $context; + } + $return['@context'] = $c; + } + if ($this->id !== "") { + $return['id'] = $this->id; + } + $return['type'] = $this->type; + + if ($this->content !== "") { + $return['content'] = $this->content; + } + + if ($this->duration !== false) { + $return['duration'] = $this->duration->format("P%yY%mM%dDT%hH%iM%sS"); + } + if ($this->height != -1) { + $return['height'] = $this->height; + } + if ($this->href !== "") { + $return['href'] = $this->href; + } + if ($this->endTime > 0) { + $return['endTime'] = gmdate("Y-m-d\TH:i:s\Z", $this->endTime); + } + if ($this->width != -1) { + $return['width'] = $this->width; + } + if (sizeof($this->attachment) > 0) { + $attachment = []; + foreach($this->attachment as $a) { + $attachment[] = $a->toObject(); + } + $return['attachment'] = $attachment; + } + if ($this->attributedTo !== "") { + $return['attributedTo'] = $this->attributedTo; + } + if ($this->name !== "") { + $return['name'] = $this->name; + } + if (sizeof($this->icon) > 0 ) { + if (sizeof($this->icon) > 1) { + $icons = []; + foreach($this->icon as $icon) { + $icons[] = $icon->toObject(); + } + $return['icon'] = $icons; + } else { + $return['icon'] = $this->icon[0]->toObject(); + } + } + if (sizeof($this->image) > 0 ) { + $images = []; + foreach($this->image as $image) { + $images[] = $image->toObject(); + } + $return['image'] = $images; + } + if ($this->inReplyTo !== "") { + $return['inReplyTo'] = $this->inReplyTo; + } + if ($this->published > 0) { + $return['published'] = gmdate("Y-m-d\TH:i:s\Z", $this->published); + } + if ($this->summary !== "") { + $return['summary'] = $this->summary; + } + if (sizeof($this->tag) > 0) { + $tags = []; + foreach($this->tag as $tag) { + $tags[] = $tag->toObject(); + } + $return['tag'] = $tags; + } + if ($this->updated > 0) { + $return['updated'] = gmdate("Y-m-d\TH:i:S\Z", $this->updated); + } + if ($this->url !== '') { + $return['url'] = $this->url; + } + if (sizeof($this->to) > 0) { + $return['to'] = $this->to; + } + if (sizeof($this->cc) > 0) { + $return['cc'] = $this->cc; + } + if ($this->mediaType !== '') { + $return['mediaType'] = $this->mediaType; + } + if ($this->object !== null) { + $return['object'] = $this->object->toObject(); + } + if ($this->atomURI !== '') { + $return['atomUri'] = $this->atomURI; + } + if ($this->replyAtomURI !== null) { + $return['inReplyTo'] = $this->replyAtomURI; + $return['inReplyToAtomUri'] = $this->replyAtomURI; + } + if ($this->sensitive !== null) { + $return['sensitive'] = $this->sensitive; + } + if ($this->blurhash !== '') { + $return['blurhash'] = $this->blurhash; + } + if ($this->conversation !== '') { + $return['conversation'] = $this->conversation; + } + if ($this->uuid !== '') { + $return['uuid'] = $this->uuid; + } + return $return; + } + + /** + * set uuid + * @param string $id + */ + public function setUUID(string $id) : void { + $this->uuid = $id; + } + + public function getUUID() : string { + return $this->uuid; + } + public static function parseDateTime(string $input) : int { + $timestamp = 0; + if (strpos($input, "T")!== false) { + $date = \DateTime::createFromFormat('Y-m-d\TH:i:sT', $input); + if ($date === false) { + $date = \DateTime::createFromFormat('Y-m-d\TH:i:s+', $input); + } + if ($date !== false) { + $timestamp = $date->getTimestamp(); + } else { + error_log("date parsing error ". $input); + } + } else { + $timestamp = intval($input, 10); + } + return $timestamp; + } + +} diff --git a/src/ContentNation/ActivityPub/Common/Accept.php b/src/ContentNation/ActivityPub/Common/Accept.php new file mode 100644 index 0000000..f0ffa82 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Accept.php @@ -0,0 +1,11 @@ +actor = $actor; + } + + public function getAActor() : string { + return $this->actor; + } + + /** + * create from json/array + * @param mixed $json + */ + public function fromJson($json) : bool { + if (array_key_exists('actor', $json)) { + $this->actor = $json['actor']; + unset($json['actor']); + } + if (!parent::fromJson($json)) { + return false; + } + return true; + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + if ($this->actor !== '') { + $return['actor'] = $this->actor; + } + return $return; + } + + /** + * get Child Object + * @return Note|false + */ + public function getObject() { + return parent::getObject(); + } +} diff --git a/src/ContentNation/ActivityPub/Common/Announce.php b/src/ContentNation/ActivityPub/Common/Announce.php new file mode 100644 index 0000000..d491ca0 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Announce.php @@ -0,0 +1,44 @@ +object = $object; + } + + public function getAObject() : string { + return $this->object; + } + + public function __construct() { + parent::__construct('Announce'); + parent::addContext('https://www.w3.org/ns/activitystreams'); + } + public function fromJson($json) : bool { + if (array_key_exists('object', $json)) { + $this->object = $json['object']; + unset($json['object']); + } + return parent::fromJson($json); + } + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + if ($this->object !== "") { + $return['object'] = $this->object; + } + return $return; + } + +} \ No newline at end of file diff --git a/src/ContentNation/ActivityPub/Common/Article.php b/src/ContentNation/ActivityPub/Common/Article.php new file mode 100644 index 0000000..d475b56 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Article.php @@ -0,0 +1,18 @@ + + */ + public function toObject() { + $return = parent::toObject(); + $return['type'] = 'Collection'; + if ($this->totalItems > 0) { + $return['totalItems'] = $this->totalItems; + } + if ($this->first !== '') { + $return['first'] = $this->first; + } + if ($this->last !== '') { + $return['last'] = $this->last; + } + return $return; + } + + /** + * create object from json + * @param array $json input json + * @return bool true on success + */ + public function fromJson($json) : bool { + return parent::fromJson($json); + } + + public function count() : int { + return $this->totalItems; + } + + public function setFirst(string $url) : void { + $this->first = $url; + } + + public function setLast(string $url) : void { + $this->last = $url; + } + +} diff --git a/src/ContentNation/ActivityPub/Common/Create.php b/src/ContentNation/ActivityPub/Common/Create.php new file mode 100644 index 0000000..d17c400 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Create.php @@ -0,0 +1,27 @@ + + */ + public function toObject() { + $return = parent::toObject(); + $return['type'] = 'Create'; + return $return; + } + + /** + * create object from json + * @param array $json input json + * @return bool true on success + */ + public function fromJson($json) : bool { + return parent::fromJson($json); + } +} diff --git a/src/ContentNation/ActivityPub/Common/Delete.php b/src/ContentNation/ActivityPub/Common/Delete.php new file mode 100644 index 0000000..eaa0a3f --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Delete.php @@ -0,0 +1,45 @@ +object = $object; + } + + public function __construct() { + parent::__construct('Delete'); + parent::addContext('https://www.w3.org/ns/activitystreams'); + } + + /** + * create from json/array + * @param mixed $json + */ + public function fromJson($json) : bool { + if (array_key_exists('object', $json)) { + $this->object = $json['object']; + unset($json['object']); + } + return parent::fromJson($json); + } + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + if ($this->object !== "") { + $return['object'] = $this->object; + } + return $return; + } + +} \ No newline at end of file diff --git a/src/ContentNation/ActivityPub/Common/Document.php b/src/ContentNation/ActivityPub/Common/Document.php new file mode 100644 index 0000000..bdf458c --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Document.php @@ -0,0 +1,9 @@ + + */ + public function toObject() { + $return = parent::toObject(); + return $return; + } + +} \ No newline at end of file diff --git a/src/ContentNation/ActivityPub/Common/Follow.php b/src/ContentNation/ActivityPub/Common/Follow.php new file mode 100644 index 0000000..5006ce2 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Follow.php @@ -0,0 +1,38 @@ +object = $object; + } + + public function __construct() { + parent::__construct("Follow"); + } + + public function fromJson($json) : bool { + if (array_key_exists('object', $json)) { + $this->object = $json['object']; + unset($json['object']); + } + return parent::fromJson($json); + } + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + if ($this->object !== "") { + $return['object'] = $this->object; + } + return $return; + } +} \ No newline at end of file diff --git a/src/ContentNation/ActivityPub/Common/Image.php b/src/ContentNation/ActivityPub/Common/Image.php new file mode 100644 index 0000000..6cc6ff9 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Image.php @@ -0,0 +1,49 @@ +mediaType = $mediaType; + return $this; + } + + /** + * create object from json + * @param mixed $json input + */ + public function fromJson($json) : bool { + if (!parent::fromJson($json)) { + return false; + } + if (array_key_exists('url', $json)) { + $this->url = $json['url']; + } + if (array_key_exists('mediaType', $json)) { + $this->mediaType = $json['mediaType']; + } + return true; + } +} diff --git a/src/ContentNation/ActivityPub/Common/IntransitiveActivity.php b/src/ContentNation/ActivityPub/Common/IntransitiveActivity.php new file mode 100644 index 0000000..317aff1 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/IntransitiveActivity.php @@ -0,0 +1,34 @@ + + */ + public function toObject() { + $return = parent::toObject(); + unset($return['object']); + return $return; + } +} diff --git a/src/ContentNation/ActivityPub/Common/Note.php b/src/ContentNation/ActivityPub/Common/Note.php new file mode 100644 index 0000000..b5ba84f --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Note.php @@ -0,0 +1,77 @@ +sender = $sender; + return $this; + } + + /** + * get sender + * @return string sender + */ + public function getSender() : string { + return $this->sender; + } + + /** + * set receiver + * @param string $receiver note receiver + * @return Note current instance + */ + public function setReceiver(string $receiver) : Note { + $this->receiver = $receiver; + return $this; + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + if ($this->sender !== "") { + $return['sender'] = $this->sender; + } + if ($this->receiver !== "") { + $return['receiver'] = $this->receiver; + } + return $return; + } + + /** + * create object from json + * @param mixed $json input json + */ + public function fromJson($json) : bool { + if (!parent::fromJson($json)) + return false; + $this->receiver = ""; + return true; + } +} diff --git a/src/ContentNation/ActivityPub/Common/OrderedCollection.php b/src/ContentNation/ActivityPub/Common/OrderedCollection.php new file mode 100644 index 0000000..127bc25 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/OrderedCollection.php @@ -0,0 +1,71 @@ + + */ + public function toObject() { + $return = parent::toObject(); + $return['type'] = 'OrderedCollection'; + if ($this->totalItems > 0) { + foreach($this->items as $item) { + $return['OrderedItems'][] = $item->toObject(); + } + } + return $return; + } + + /** + * create object from json + * @param array $json input json + * @return bool true on success + */ + public function fromJson($json) : bool { + return parent::fromJson($json); + } + + public function append(APObject &$item) : void { + $this->items[] = $item; + $this->totalItems = sizeof($this->items); + } + + /** + * get item with given index + * @return APObject|false + */ + public function get(int $index) { + if ($index >= 0) { + if ($index >= $this->totalItems) { + return false; + } + return $this->items[$index]; + } else { + if ($this->totalItems+ $index < 0) { + return false; + } + return $this->items[$this->totalItems + $index]; + } + } + + /** + * set items + * @param APObject[] $items + */ + public function setItems(&$items) : void { + $this->items = $items; + $this->totalItems = sizeof($items); + } +} diff --git a/src/ContentNation/ActivityPub/Common/OrderedCollectionPage.php b/src/ContentNation/ActivityPub/Common/OrderedCollectionPage.php new file mode 100644 index 0000000..902d8e9 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/OrderedCollectionPage.php @@ -0,0 +1,55 @@ + + */ + public function toObject() { + $return = parent::toObject(); + if ($this->next !== '') { + $return['next'] = $this->next; + } + if ($this->prev !== '') { + $return['prev'] = $this->prev; + } + if ($this->partOf !== '') { + $return['partOf'] = $this->partOf; + } + return $return; + } + + /** + * create object from json + * @param array $json input json + * @return bool true on success + */ + public function fromJson($json) : bool { + return parent::fromJson($json); + } + + public function setNext(string $url) : void { + $this->next = $url; + } + + public function setPrev(string $url) : void { + $this->prev = $url; + } + + public function setPartOf(string $url) : void { + $this->partOf = $url; + } + +} diff --git a/src/ContentNation/ActivityPub/Common/Outbox.php b/src/ContentNation/ActivityPub/Common/Outbox.php new file mode 100644 index 0000000..a75ebfa --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Outbox.php @@ -0,0 +1,38 @@ + "http://ostatus.org#", + "atomUri" => "ostatus:atomUri", + "inReplyToAtomUri" => "ostatus:inReplyToAtomUri", + "conversation" => "ostatus:conversation", + "sensitive" => "as:sensitive", + "toot" => "http://joinmastodon.org/ns#", + "votersCount" => "toot:votersCount", + "Hashtag" => "as:Hashtag" + )); + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + return $return; + } + + /** + * create object from json + * @param array $json input json + * @return bool true on success + */ + public function fromJson($json) : bool { + return parent::fromJson($json); + } +} diff --git a/src/ContentNation/ActivityPub/Common/Page.php b/src/ContentNation/ActivityPub/Common/Page.php new file mode 100644 index 0000000..7bc42e2 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Page.php @@ -0,0 +1,9 @@ + + */ + public function toObject() { + $return = parent::toObject(); + $return['votersCount'] = $this->votersCount; + return $return; + } + + /** + * create object from json + * @param mixed $json input json + */ + public function fromJson($json) : bool { + if (array_key_exists('votersCount', $json)) { + $this->votersCount = intval($json['votersCount'], 10); + } + return parent::fromJson($json); + } +} diff --git a/src/ContentNation/ActivityPub/Common/Stats.php b/src/ContentNation/ActivityPub/Common/Stats.php new file mode 100644 index 0000000..7cb25d8 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Stats.php @@ -0,0 +1,48 @@ +userCount = $count; + return $this; + } + + /** + * set page count + * @param int $count page count + * @return Stats current instance + */ + public function setPageCount(int $count) : Stats { + $this->pageCount = $count; + return $this; + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $ret = array( + "user_count"=> $this->userCount, + "status_count"=> $this->pageCount + ); + return $ret; + } +} diff --git a/src/ContentNation/ActivityPub/Common/Tag.php b/src/ContentNation/ActivityPub/Common/Tag.php new file mode 100644 index 0000000..dc3f2dc --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Tag.php @@ -0,0 +1,22 @@ +setType($json['type']); + } + return true; + } +} diff --git a/src/ContentNation/ActivityPub/Common/Undo.php b/src/ContentNation/ActivityPub/Common/Undo.php new file mode 100644 index 0000000..9bcb625 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Undo.php @@ -0,0 +1,21 @@ + + */ + public function toObject() { + $return = parent::toObject(); + return $return; + } +} \ No newline at end of file diff --git a/src/ContentNation/ActivityPub/Common/User.php b/src/ContentNation/ActivityPub/Common/User.php new file mode 100644 index 0000000..bf9e3b8 --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/User.php @@ -0,0 +1,294 @@ +> + */ + private $fields = []; + + /** + * Set user name + * @param string $userName user name + * @return User current instance + */ + public function setUserName(string $userName) : User { + $this->userName = $userName; + return $this; + } + + /** + * Set account name + * @param string $accountName account name + * @return User current instance + */ + public function setAccountName(string $accountName) : User { + $this->accountName = $accountName; + return $this; + } + + /** + * Set display name + * @param string $displayName display name + * @return User current instance + */ + public function setDisplayName(string $displayName) : User { + $this->displayName = $displayName; + return $this; + } + + /** + * Set locked status + * @param bool $locked locked status + * @return User current instance + */ + public function setLocked(bool $locked) : User { + $this->locked = $locked; + return $this; + } + + /** + * Set bot status + * @param bool $bot bot status + * @return User current instance + */ + public function setBot(bool $bot) : User { + $this->bot = $bot; + return $this; + } + + /** + * Set discoverable status + * @param bool $discoverable discoverable status + * @return User current instance + */ + public function setDiscoverable(bool $discoverable) : User { + $this->discoverable = $discoverable; + return $this; + } + + /** + * Set group flag + * @param bool $group group flag + * @return User current instance + */ + public function setGroupFlag(bool $group) : User { + $this->group = $group; + return $this; + } + + /** + * Set created timestamp + * @param int $timestamp timestamp + * @return User current instance + */ + public function setCreated(int $timestamp) : User { + $this->created = $timestamp; + return $this; + } + + /** + * Set note + * @param string $note note + * @return User current instance + */ + public function setNote(string $note) : User { + $this->note = $note; + return $this; + } + + /** + * Set URL + * @param string $url url + * @return User current instance + */ + public function setURL(string $url) : User { + $this->url = $url; + return $this; + } + + /** + * Set avatar URL + * @param string $url url + * @return User current instance + */ + public function setAvatarURL(string $url) : User { + $this->avatarURL = $url; + return $this; + } + + /** + * Set header URL + * @param string $url url + * @return User current instance + */ + public function setHeaderURL(string $url) : User { + $this->headerURL = $url; + return $this; + } + + /** + * Set follower count + * @param int $count follower count + * @return User current instance + */ + public function setFollowerCount(int $count) : User { + $this->followerCount = $count; + return $this; + } + + /** + * Set stats count + * @param int $count status count + * @return User current instance + */ + public function setStatusCount(int $count) : User { + $this->statusCount = $count; + return $this; + } + + /** + * Set last status timestamp + * @param int $timestamp status timestamp + * @return User current instance + */ + public function setLastStatus(int $timestamp) : User { + $this->lastStatus = $timestamp; + return $this; + } + + /** + * Add field entry + * @param string $name field name + * @param string $value field value + * @param int $verified verified timestamp + * @return User current instance + */ + public function addField(string $name, string $value, int $verified) : User { + $this->fields[] = array( + "name" => $name, + "value" => $value, + "verified_at" => ($verified > 0) ? gmdate("Y-m-d\TH:i:S\Z", $verified) : null + ); + return $this; + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = array( + "username" => $this->userName, + "acct" => $this->accountName, + "display_name" => $this->displayName, + "locked" => $this->locked, + "bot" => $this->bot, + "discoverable" => $this->discoverable, + "group" => $this->group, + "created_at" => gmdate("Y-m-d\TH:i:S\Z", $this->created), + "note" => $this->note, + "url" => $this->url, + "avatar" => $this->avatarURL, + "avatar_static" => $this->avatarURL, + "header" => $this->headerURL, + "header_static" => $this->headerURL, + "followers_count" => $this->followerCount, + "statuses_count" => $this->statusCount, + "emojis" => [], + "fields" => $this->fields + ); + if ($this->lastStatus > 0) $return['last_status_at'] = gmdate("Y-m-d", $this->lastStatus); + return $return; + } +} diff --git a/src/ContentNation/ActivityPub/Common/Video.php b/src/ContentNation/ActivityPub/Common/Video.php new file mode 100644 index 0000000..406a7ab --- /dev/null +++ b/src/ContentNation/ActivityPub/Common/Video.php @@ -0,0 +1,37 @@ + $json input + */ + public function fromJson($json) : bool { + if (array_key_exists('isLiveBroadcast', $json)) { + $this->isLiveBroadcast = $json['isLiveBroadcast']; + } + return parent::fromJson($json); + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = parent::toObject(); + if ($this->isLiveBroadcast !== null ) { + $return['isLiveBroadcast'] = $this->isLiveBroadcast; + } + return $return; + } +} \ No newline at end of file diff --git a/src/ContentNation/ActivityPub/Factory.php b/src/ContentNation/ActivityPub/Factory.php new file mode 100644 index 0000000..78b595f --- /dev/null +++ b/src/ContentNation/ActivityPub/Factory.php @@ -0,0 +1,302 @@ + $json input json + * @return Common\APObject|false object or false on error + */ + static function newFromJson($json, string $jsonstring) { + if (gettype($json) !== "array") { + error_log("newFromJson called with ".gettype($json). " => ". debug_backtrace()[1]['function'] . " json: " . print_r($json, true)); + return false; + } + if (!array_key_exists('type', $json)) { + return false; + } + $return = false; + switch($json['type']) { + case 'Article': + $return = Factory::newArticle(); + break; + case 'Document': + $return = Factory::newDocument(); + break; + case 'Event': + $return = Factory::newEvent(); + break; + case 'Follow': + $return = Factory::newFollow(); + break; + case 'Image': + $return = Factory::newImage(); + /*error_log("Image: ". print_r($json, true)); + error_log("Image json " . $jsonstring);*/ + break; + case 'Note': + $return = Factory::newNote(); + break; + case 'Question': + $return = Factory::newQuestion(); + break; + case 'Video': + // error_log("newFromJson: video " . $jsonstring); + $return = Factory::newVideo(); + break; + default: + error_log("newFromJson: unknown type: '" . $json['type'] . "' " . $jsonstring); + error_log(print_r($json, true)); + } + if ($return !== false && $return->fromJson($json)) { + return $return; + } + return false; + } + /** + * create object tree from json + * @param array $json input json + * @return Common\Activity|false object or false on error + */ + static function newActivityFromJson($json) { + if (!array_key_exists('type', $json)) { + return false; + } + $return = false; + switch($json['type']) { + case 'Accept': + $return = Factory::newAccept(); + break; + case 'Announce': + $return = Factory::newAnnounce(); + break; + case 'Create': + $return = Factory::newCreate(); + break; + case 'Delete': + $return = Factory::newDelete(); + break; + case 'Follow': + $return = Factory::newFollow(); + break; + case 'Undo': + $return = Factory::newUndo(); + break; + default: + error_log("newActivityFromJson " . print_r($json, true)); + echo "unknown activity type: '" . $json['type'] . "'\n"; + } + if ($return !== false && $return->fromJson($json)) { + return $return; + } + return false; + } +} diff --git a/src/ContentNation/ActivityPub/Message/Create.php b/src/ContentNation/ActivityPub/Message/Create.php new file mode 100644 index 0000000..6a8c504 --- /dev/null +++ b/src/ContentNation/ActivityPub/Message/Create.php @@ -0,0 +1,70 @@ +id = $id; + return $this; + } + + /** + * set actor + * @param string $actor new actor + * @return Create current instance + */ + public function setActor(string $actor) : Create { + $this->actor = $actor; + return $this; + } + + /** + * set object to create + * @param \ContentNation\ActivityPub\Common\APObject $object object to create + * @return Create current instance + */ + public function setObject(\ContentNation\ActivityPub\Common\APObject $object) : Create { + $this->object = $object; + return $this; + } + + /** + * convert internal state to php array + * @return array + */ + public function toObject() { + $return = array( + '@context' => 'https://www.w3.org/ns/activitystreams', + 'id' => $this->id, + 'type' => 'Create', + 'actor' => $this->actor, + ); + if ($this->object !== null) { + $return['object'] = $this->object->toObject(); + } + return $return; + } + +} diff --git a/src/ContentNation/ActivityPub/Response/Instance.php b/src/ContentNation/ActivityPub/Response/Instance.php new file mode 100644 index 0000000..f15c9c0 --- /dev/null +++ b/src/ContentNation/ActivityPub/Response/Instance.php @@ -0,0 +1,235 @@ +uri = $uri; + return $this; + } + + /** + * Set title + * @param string $title + * @return Instance current instance + */ + public function setTitle(string $title) : Instance { + $this->title = $title; + return $this; + } + + /** + * Set short description + * @param string $short + * @return Instance current instance + */ + public function setShortDescription(string $short) : Instance { + $this->shortDescription = $short; + return $this; + } + + /** + * Set description + * @param string $description + * @return Instance current instance + */ + public function setDescription(string $description) : Instance { + $this->description = $description; + return $this; + } + + /** + * Set E-Mail + * @param string $email + * @return Instance current instance + */ + public function setEmail(string $email) : Instance { + $this->email = $email; + return $this; + } + + /** + * Set version + * @param string $version + * @return Instance current instance + */ + public function setVersion(string $version) : Instance { + $this->version = $version; + return $this; + } + + /** + * Set thumbnail image + * @param string $thumbnail + * @return Instance current instance + */ + public function setThumbnail(string $thumbnail) : Instance { + $this->thumbnail = $thumbnail; + return $this; + } + + /** + * Set registration allowed + * @param bool $allowed + * @return Instance current instance + */ + public function setRegistration(bool $allowed) : Instance { + $this->registration = $allowed; + return $this; + } + + /** + * Set approval required + * @param bool $required + * @return Instance current instance + */ + public function setApproval(bool $required) : Instance { + $this->approval = $required; + return $this; + } + + /** + * Set invited enabled + * @param bool $invites + * @return Instance current instance + */ + public function setInvites(bool $invites) : Instance { + $this->invites = $invites; + return $this; + } + + /** + * Set languages + * @param string[] $languages + * @return Instance current instance + */ + public function setLanguages($languages) : Instance { + $this->languages = $languages; + return $this; + } + + /** + * Set stats object + * @param \ContentNation\ActivityPub\Common\Stats $stats + * @return Instance current instance + */ + public function setStats($stats) : Instance { + $this->stats = $stats; + return $this; + } + + /** + * Set contact object + * @param \ContentNation\ActivityPub\Common\User $user + * @return Instance current instance + */ + public function setcontact($user) : Instance { + $this->contact = $user; + return $this; + } + + /** + * convert internal state to php array + * @return array + */ + function toObject() { + $return = array( + 'uri' => $this->uri, + 'title' => $this->title, + 'short_description' => $this->shortDescription, + 'description' => $this->description, + 'email' => $this->email, + 'version' => $this->version, + 'thumbnail' => $this->thumbnail, + 'registrations' => $this->registration, + 'approval_required' => $this->approval, + 'invites_enabled' => $this->invites, + 'languages'=> $this->languages, + ); + if ($this->stats !== null) $return['stats'] = $this->stats->toObject(); + if ($this->contact !== null) $return['contact_account'] = $this->contact->toObject(); + return $return; + } +} diff --git a/src/ContentNation/manualloader.php b/src/ContentNation/manualloader.php new file mode 100644 index 0000000..bd3694e --- /dev/null +++ b/src/ContentNation/manualloader.php @@ -0,0 +1,8 @@ +