forked from grumpydevelop/federator
		
	incomplete support for fetching data from user outbox (only article yet)
This commit is contained in:
		
							parent
							
								
									61203001a3
								
							
						
					
					
						commit
						d208afe899
					
				
					 28 changed files with 2125 additions and 21 deletions
				
			
		| 
						 | 
				
			
			@ -1,2 +0,0 @@
 | 
			
		|||
[contentnation]
 | 
			
		||||
service-uri = http://local.contentnation.net
 | 
			
		||||
							
								
								
									
										12
									
								
								lang/federator/de/article.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lang/federator/de/article.inc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
$l = [
 | 
			
		||||
    'image' => 'Artikelbild',
 | 
			
		||||
    'newarticle' => 'Ein neuer Artikel wurde veröffentlicht',
 | 
			
		||||
];
 | 
			
		||||
							
								
								
									
										12
									
								
								lang/federator/en/article.inc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								lang/federator/en/article.inc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
$l = [
 | 
			
		||||
    'image' => 'article image',
 | 
			
		||||
    'newarticle' => 'A new Artikel was published',
 | 
			
		||||
];
 | 
			
		||||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
 namespace Federator\Api;
 | 
			
		||||
namespace Federator\Api;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * /@username or /users/ handlers
 | 
			
		||||
| 
						 | 
				
			
			@ -48,14 +48,50 @@ class FedUsers implements APIInterface
 | 
			
		|||
    public function exec($paths, $user)
 | 
			
		||||
    {
 | 
			
		||||
        $method = $_SERVER["REQUEST_METHOD"];
 | 
			
		||||
        switch ($method) {
 | 
			
		||||
            case 'GET':
 | 
			
		||||
                switch (sizeof($paths)) {
 | 
			
		||||
                    case 2:
 | 
			
		||||
                        // /users/username or /@username
 | 
			
		||||
                        return $this->returnUserProfile($paths[1]);
 | 
			
		||||
        $handler = null;
 | 
			
		||||
        switch (sizeof($paths)) {
 | 
			
		||||
            case 2:
 | 
			
		||||
                if ($method === 'GET') {
 | 
			
		||||
                    // /users/username or /@username
 | 
			
		||||
                    return $this->returnUserProfile($paths[1]);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case 3:
 | 
			
		||||
                // /users/username/(inbox|outbox|following|followers)
 | 
			
		||||
                switch ($paths[2]) {
 | 
			
		||||
                    case 'following':
 | 
			
		||||
                        // $handler = new FedUsers\Following();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'followers':
 | 
			
		||||
                        // $handler = new FedUsers\Followers();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'inbox':
 | 
			
		||||
                        // $handler = new FedUsers\Inbox();
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'outbox':
 | 
			
		||||
                        $handler = new FedUsers\Outbox($this->main);
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            case 4:
 | 
			
		||||
                // /users/username/collections/(features|tags)
 | 
			
		||||
                // not yet implemented
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        if ($handler !== null) {
 | 
			
		||||
            $ret = false;
 | 
			
		||||
            switch ($method) {
 | 
			
		||||
                case 'GET':
 | 
			
		||||
                    $ret = $handler->get($paths[1]);
 | 
			
		||||
                    break;
 | 
			
		||||
                case 'POST':
 | 
			
		||||
                    $ret = $handler->post($paths[1]);
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
            if ($ret !== false) {
 | 
			
		||||
                $this->response = $ret;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $this->main->setResponseCode(404);
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										28
									
								
								php/federator/api/fedusers/fedusersinterface.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								php/federator/api/fedusers/fedusersinterface.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Api\FedUsers;
 | 
			
		||||
 | 
			
		||||
interface FedUsersInterface
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * get call for user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $_user user to fetch data for
 | 
			
		||||
     * @return string|false response or false in case of error
 | 
			
		||||
     */
 | 
			
		||||
    public function get($_user);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * post call for user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $_user user to add data to
 | 
			
		||||
     * @return string|false response or false in case of error
 | 
			
		||||
     */
 | 
			
		||||
    public function post($_user);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								php/federator/api/fedusers/outbox.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								php/federator/api/fedusers/outbox.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,95 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Api\FedUsers;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * handle activitypub outbox requests
 | 
			
		||||
 */
 | 
			
		||||
class Outbox implements \Federator\Api\FedUsers\FedUsersInterface
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * main instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var \Federator\Main $main
 | 
			
		||||
     */
 | 
			
		||||
    private $main;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     * @param \Federator\Main $main main instance
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($main)
 | 
			
		||||
    {
 | 
			
		||||
        $this->main = $main;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * handle get call
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $_user user to fetch outbox for
 | 
			
		||||
     * @return string|false response
 | 
			
		||||
     */
 | 
			
		||||
    public function get($_user)
 | 
			
		||||
    {
 | 
			
		||||
        $dbh = $this->main->getDatabase();
 | 
			
		||||
        $cache = $this->main->getCache();
 | 
			
		||||
        $connector = $this->main->getConnector();
 | 
			
		||||
        // get user
 | 
			
		||||
        $user = \Federator\DIO\User::getUserByName(
 | 
			
		||||
            $dbh,
 | 
			
		||||
            $_user,
 | 
			
		||||
            $connector,
 | 
			
		||||
            $cache
 | 
			
		||||
        );
 | 
			
		||||
        if ($user->id === null) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        // get posts from user
 | 
			
		||||
        $outbox = new \Federator\Data\ActivityPub\Common\Outbox();
 | 
			
		||||
        $min = $this->main->extractFromURI("min", "");
 | 
			
		||||
        $max = $this->main->extractFromURI("max", "");
 | 
			
		||||
        $page = $this->main->extractFromURI("page", "");
 | 
			
		||||
        if ($page !== "") {
 | 
			
		||||
            $items = \Federator\DIO\Posts::getPostsByUser($dbh, $user->id, $connector, $cache, $min, $max);
 | 
			
		||||
            $outbox->setItems($items);
 | 
			
		||||
        } else {
 | 
			
		||||
            $items = [];
 | 
			
		||||
        }
 | 
			
		||||
        $host = $_SERVER['SERVER_NAME'];
 | 
			
		||||
        $id = 'https://' . $host .'/' . $_user . '/outbox';
 | 
			
		||||
        $outbox->setPartOf($id);
 | 
			
		||||
        $outbox->setID($id);
 | 
			
		||||
        if ($page !== '') {
 | 
			
		||||
            $id .= '?page=' . urlencode($page);
 | 
			
		||||
        }
 | 
			
		||||
        if ($page === '' || $outbox->count() == 0) {
 | 
			
		||||
            $outbox->setFirst($id);
 | 
			
		||||
            $outbox->setLast($id . '&min=0');
 | 
			
		||||
        }
 | 
			
		||||
        if (sizeof($items)>0) {
 | 
			
		||||
            $newestId = $items[0]->getPublished();
 | 
			
		||||
            $oldestId = $items[sizeof($items)-1]->getPublished();
 | 
			
		||||
            $outbox->setNext($id . '&max=' . $newestId);
 | 
			
		||||
            $outbox->setPrev($id . '&min=' . $oldestId);
 | 
			
		||||
        }
 | 
			
		||||
        $obj = $outbox->toObject();
 | 
			
		||||
        return json_encode($obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * handle post call
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $_user user to add data to outbox @unused-param
 | 
			
		||||
     * @return string|false response
 | 
			
		||||
     */
 | 
			
		||||
    public function post($_user)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										9
									
								
								php/federator/cache/cache.php
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								php/federator/cache/cache.php
									
										
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -13,6 +13,15 @@ namespace Federator\Cache;
 | 
			
		|||
 */
 | 
			
		||||
interface Cache extends \Federator\Connector\Connector
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * save remote posts by user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $user user name
 | 
			
		||||
     * @param \Federator\Data\ActivityPub\Common\APObject[]|false $posts user posts
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function saveRemotePostsByUser($user, $posts);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * save remote stats
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,17 @@ namespace Federator\Connector;
 | 
			
		|||
 */
 | 
			
		||||
interface Connector
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * get posts by given user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $id user id
 | 
			
		||||
     * @param string $minId min ID
 | 
			
		||||
     * @param string $maxId max ID
 | 
			
		||||
 | 
			
		||||
     * @return \Federator\Data\ActivityPub\Common\APObject[]|false
 | 
			
		||||
     */
 | 
			
		||||
    public function getRemotePostsByUser($id, $minId, $maxId);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get remote user by given name
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										89
									
								
								php/federator/data/activitypub/common/activity.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								php/federator/data/activitypub/common/activity.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Activity extends APObject
 | 
			
		||||
{
 | 
			
		||||
    // actor | object | target | result | origin | instrument
 | 
			
		||||
    /**
 | 
			
		||||
     * actor
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $actor
 | 
			
		||||
     */
 | 
			
		||||
    private $actor = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     *
 | 
			
		||||
     * @param ?string $type type
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($type = null)
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct($type ?? "Activity");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set actor
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $actor new actor
 | 
			
		||||
     * @return Activity
 | 
			
		||||
     */
 | 
			
		||||
    public function setAActor(string $actor)
 | 
			
		||||
    {
 | 
			
		||||
        $this->actor = $actor;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAActor() : string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->actor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create from json/array
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $json
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        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<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    public function toObject()
 | 
			
		||||
    {
 | 
			
		||||
        $return = parent::toObject();
 | 
			
		||||
        if ($this->actor !== '') {
 | 
			
		||||
            $return['actor'] = $this->actor;
 | 
			
		||||
        }
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get Child Object
 | 
			
		||||
     *
 | 
			
		||||
     * @return APObject|null
 | 
			
		||||
     */
 | 
			
		||||
    public function getObject()
 | 
			
		||||
    {
 | 
			
		||||
        return parent::getObject();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										951
									
								
								php/federator/data/activitypub/common/apobject.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										951
									
								
								php/federator/data/activitypub/common/apobject.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,951 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class APObject implements \JsonSerializable
 | 
			
		||||
{
 | 
			
		||||
    // actor | bto | current | first | id | instrument | last | items | oneOf |
 | 
			
		||||
    // anyOf | closed | origin | next | object | prev | result | target |
 | 
			
		||||
    // type | accuracy | altitude | content | duration | height | href | hreflang |
 | 
			
		||||
    // partOf | latitude | longitude | endTime | radius | rel |
 | 
			
		||||
    // startIndex | totalItems | units | width | subject | relationship | describes |
 | 
			
		||||
    // formerType | deleted
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * unique id
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $id
 | 
			
		||||
     */
 | 
			
		||||
    private $id = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * child object
 | 
			
		||||
     *
 | 
			
		||||
     * @var APObject|null $object
 | 
			
		||||
     */
 | 
			
		||||
    private $object = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * type
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $type
 | 
			
		||||
     */
 | 
			
		||||
    private $type = 'Object';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * content
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $content
 | 
			
		||||
     */
 | 
			
		||||
    private $content = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * duration in seconds
 | 
			
		||||
     *
 | 
			
		||||
     * @var \DateInterval|false $duration
 | 
			
		||||
     */
 | 
			
		||||
    private $duration = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * height
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $height
 | 
			
		||||
     */
 | 
			
		||||
    private $height = -1;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * href
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $href
 | 
			
		||||
     */
 | 
			
		||||
    private $href = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * end time
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $endTime
 | 
			
		||||
     */
 | 
			
		||||
    private $endTime = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * width
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $width
 | 
			
		||||
     */
 | 
			
		||||
    private $width = -1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // fiels are attachment | attributedTo | audience | content | context | name | endTime | generator |
 | 
			
		||||
    // icon | image | inReplyTo | location | preview | published | replies | startTime | summary | tag |
 | 
			
		||||
    // updated | url | to | bto | cc | bcc | mediaType | duration
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * attachements
 | 
			
		||||
     *
 | 
			
		||||
     * @var APObject[] $attachment
 | 
			
		||||
     */
 | 
			
		||||
    private $attachment = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * attributed to
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $attributedTo
 | 
			
		||||
     */
 | 
			
		||||
    private $attributedTo = '';
 | 
			
		||||
 | 
			
		||||
    // audience
 | 
			
		||||
    // content
 | 
			
		||||
    // context
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * name
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $name
 | 
			
		||||
     */
 | 
			
		||||
    private $name = '';
 | 
			
		||||
 | 
			
		||||
    // endTime
 | 
			
		||||
    // generator
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * images
 | 
			
		||||
     * @var Image[] $icon
 | 
			
		||||
     */
 | 
			
		||||
    private $icon = array();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * images
 | 
			
		||||
     *
 | 
			
		||||
     * @var Image[] $image
 | 
			
		||||
     */
 | 
			
		||||
    private $image = array();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * reply id
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $inReplyTo
 | 
			
		||||
     */
 | 
			
		||||
    private $inReplyTo = "";
 | 
			
		||||
 | 
			
		||||
    // location
 | 
			
		||||
    // preview
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * published timestamp
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $published
 | 
			
		||||
     */
 | 
			
		||||
    private $published = 0;
 | 
			
		||||
 | 
			
		||||
    // startTime
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * summary
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $summary
 | 
			
		||||
     */
 | 
			
		||||
    private $summary = "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * tags
 | 
			
		||||
     *
 | 
			
		||||
     * @var Tag[] $tag
 | 
			
		||||
     */
 | 
			
		||||
    private $tag = array();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * updated timestamp
 | 
			
		||||
     *
 | 
			
		||||
     * @var int $updated
 | 
			
		||||
     */
 | 
			
		||||
    private $updated = 0;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * url
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $url
 | 
			
		||||
     */
 | 
			
		||||
    private $url = "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * list of to ids
 | 
			
		||||
     *
 | 
			
		||||
     * @var array<string> $to
 | 
			
		||||
     */
 | 
			
		||||
    private $to = array();
 | 
			
		||||
 | 
			
		||||
    // bto
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * list of cc ids
 | 
			
		||||
     *
 | 
			
		||||
     * @var array<string> $cc
 | 
			
		||||
     */
 | 
			
		||||
    private $cc = array();
 | 
			
		||||
 | 
			
		||||
    // bcc
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * media type
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $mediaType
 | 
			
		||||
     */
 | 
			
		||||
    private $mediaType = "";
 | 
			
		||||
 | 
			
		||||
    // duration
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * list of contexts
 | 
			
		||||
     *
 | 
			
		||||
     * @var array<string> $context
 | 
			
		||||
     */
 | 
			
		||||
    private $context = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * key value map of contexts
 | 
			
		||||
     * @var array<string, string> $contexts
 | 
			
		||||
     */
 | 
			
		||||
    private $contexts = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * atom URI
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $atomURI
 | 
			
		||||
     */
 | 
			
		||||
    private $atomURI = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * reply to atom URI
 | 
			
		||||
     *
 | 
			
		||||
     * @var ?string $replyAtomURI
 | 
			
		||||
     */
 | 
			
		||||
    private $replyAtomURI = null;
 | 
			
		||||
 | 
			
		||||
    // found items
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * generated unique id
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $uuid
 | 
			
		||||
     */
 | 
			
		||||
    private $uuid = "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * sensitive flag
 | 
			
		||||
     *
 | 
			
		||||
     * @var ?bool $sensitive
 | 
			
		||||
     */
 | 
			
		||||
    private $sensitive = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * blur hash
 | 
			
		||||
     * @var string $blurhash
 | 
			
		||||
     */
 | 
			
		||||
    private $blurhash = "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * conversation id
 | 
			
		||||
     * @var string $conversation
 | 
			
		||||
     */
 | 
			
		||||
    private $conversation = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $type type of object
 | 
			
		||||
     */
 | 
			
		||||
    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)
 | 
			
		||||
    {
 | 
			
		||||
        $this->content = $content;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get note content
 | 
			
		||||
     *
 | 
			
		||||
     * @return string
 | 
			
		||||
     */
 | 
			
		||||
    public function getContent()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->content;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * add context to list
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $context new context
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    final public function addContext($context)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array($context, $this->context, false)) {
 | 
			
		||||
            $this->context[] = $context;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * add multiple contexts to list
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string,string> $contexts new contexts
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    final public function addContexts($contexts)
 | 
			
		||||
    {
 | 
			
		||||
        foreach ($contexts as $key => $value) {
 | 
			
		||||
            if (!in_array($key, $this->contexts, false)) {
 | 
			
		||||
                $this->contexts[$key] = $value;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set id
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $id new id
 | 
			
		||||
     * @return APObject current object
 | 
			
		||||
     */
 | 
			
		||||
    final public function setID($id)
 | 
			
		||||
    {
 | 
			
		||||
        $this->id = $id;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    final public function getID() : string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set href
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $href href
 | 
			
		||||
     * @return APObject
 | 
			
		||||
     */
 | 
			
		||||
    public function setHref(string $href)
 | 
			
		||||
    {
 | 
			
		||||
        $this->href = $href;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set child object
 | 
			
		||||
     *
 | 
			
		||||
     * @param APObject $object
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setObject($object)
 | 
			
		||||
    {
 | 
			
		||||
        $this->object = $object;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get child object
 | 
			
		||||
     *
 | 
			
		||||
     * @return APObject|null child object
 | 
			
		||||
     */
 | 
			
		||||
    public function getObject()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->object;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set summary
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $summary summary
 | 
			
		||||
     * @return APObject this
 | 
			
		||||
     */
 | 
			
		||||
    public function setSummary($summary)
 | 
			
		||||
    {
 | 
			
		||||
        $this->summary = $summary;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * set type
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $type type
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setType(string $type)
 | 
			
		||||
    {
 | 
			
		||||
        $this->type = $type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getType() : string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->type;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set attachments
 | 
			
		||||
     *
 | 
			
		||||
     * @param APObject[] $attachment
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setAttachment($attachment)
 | 
			
		||||
    {
 | 
			
		||||
        $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 = [];
 | 
			
		||||
        foreach ($this->attachment as $a) {
 | 
			
		||||
            $obj[] = $a->toObject();
 | 
			
		||||
        }
 | 
			
		||||
        return json_encode($obj) | '';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set attributed to
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $to attribute to
 | 
			
		||||
     * @return APObject
 | 
			
		||||
     */
 | 
			
		||||
    public function setAttributedTo(string $to)
 | 
			
		||||
    {
 | 
			
		||||
        $this->attributedTo = $to;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAttributedTo() : string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->attributedTo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set name
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $name name
 | 
			
		||||
     * @return APObject
 | 
			
		||||
     */
 | 
			
		||||
    public function setName(string $name)
 | 
			
		||||
    {
 | 
			
		||||
        $this->name = $name;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * add Image
 | 
			
		||||
     *
 | 
			
		||||
     * @param Image $image image to add
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function addImage(Image $image)
 | 
			
		||||
    {
 | 
			
		||||
        $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
 | 
			
		||||
     * @return APObject
 | 
			
		||||
     */
 | 
			
		||||
    public function setPublished(int $published)
 | 
			
		||||
    {
 | 
			
		||||
        $this->published = $published;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getPublished() : int
 | 
			
		||||
    {
 | 
			
		||||
        return $this->published;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * add Tag
 | 
			
		||||
     *
 | 
			
		||||
     * @param Tag $tag tag to add
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function addTag(Tag $tag)
 | 
			
		||||
    {
 | 
			
		||||
        $this->tag[] = $tag;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set url
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $url URL
 | 
			
		||||
     * @return APObject
 | 
			
		||||
     */
 | 
			
		||||
    public function setURL(string $url)
 | 
			
		||||
    {
 | 
			
		||||
        $this->url = $url;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get URL
 | 
			
		||||
     *
 | 
			
		||||
     * @return string URL
 | 
			
		||||
     */
 | 
			
		||||
    public function getURL()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * add to
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $to additional to address
 | 
			
		||||
     * @return APObject
 | 
			
		||||
     */
 | 
			
		||||
    public function addTo(string $to)
 | 
			
		||||
    {
 | 
			
		||||
        $this->to[] = $to;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get to
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<string>
 | 
			
		||||
     */
 | 
			
		||||
    public function getTo()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->to;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * add cc
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $cc additional cc address
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function addCC($cc)
 | 
			
		||||
    {
 | 
			
		||||
        $this->cc[] = $cc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get cc
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<string>
 | 
			
		||||
     */
 | 
			
		||||
    public function getCC()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->cc;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getMediaType() : string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->mediaType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set atom URI
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $uri atom URI
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setAtomURI($uri)
 | 
			
		||||
    {
 | 
			
		||||
        $this->atomURI = $uri;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set reply atom URI
 | 
			
		||||
     * @param string $uri reply atom URI
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setReplyAtomURI($uri)
 | 
			
		||||
    {
 | 
			
		||||
        $this->replyAtomURI = $uri;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set sensitive
 | 
			
		||||
     *
 | 
			
		||||
     * @param bool $sensitive status
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setSensitive($sensitive)
 | 
			
		||||
    {
 | 
			
		||||
        $this->sensitive = $sensitive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set conversation id
 | 
			
		||||
     * @param string $conversation conversation ID
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setConversation(string $conversation)
 | 
			
		||||
    {
 | 
			
		||||
        $this->conversation = $conversation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getConversation() : ?string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->conversation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create from json
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string, mixed> $json input
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        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 = \Federator\Data\ActivityPub\Factory::newFromJson($a, "");
 | 
			
		||||
                if ($att !== null) {
 | 
			
		||||
                    $attachment[] = $att;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            $this->attachment = $attachment;
 | 
			
		||||
        }
 | 
			
		||||
        if (array_key_exists('attributedTo', $json)) {
 | 
			
		||||
            if (is_array($json['attributedTo']) && array_key_exists(0, $json['attributedTo'])) {
 | 
			
		||||
                if (is_array($json['attributedTo'][0])) {
 | 
			
		||||
                    $this->attributedTo = $json['attributedTo'][0]['id'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $this->attributedTo = $json['attributedTo'][0];
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                $this->attributedTo = (string)$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 = new Image();
 | 
			
		||||
                $image->fromJson($json['icon']);
 | 
			
		||||
                $this->icon[] = $image;
 | 
			
		||||
            } else {
 | 
			
		||||
                foreach ($json['icon'] as $icon) {
 | 
			
		||||
                    $image = new Image();
 | 
			
		||||
                    $image->fromJson($icon);
 | 
			
		||||
                    $this->icon[] = $image;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (array_key_exists('image', $json)) {
 | 
			
		||||
            $image = new Image();
 | 
			
		||||
            $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)) {
 | 
			
		||||
            $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 = \Federator\Data\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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     * {@inheritDoc}
 | 
			
		||||
     * @see JsonSerializable::jsonSerialize()
 | 
			
		||||
     */
 | 
			
		||||
    public function jsonSerialize()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->toObject();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * convert internal state to php array
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    public function toObject()
 | 
			
		||||
    {
 | 
			
		||||
        $return = [];
 | 
			
		||||
        if (sizeof($this->context) == 1) {
 | 
			
		||||
            $return['@context'] = array_values($this->context)[0];
 | 
			
		||||
        } elseif (sizeof($this->context) > 1) {
 | 
			
		||||
            $c = [];
 | 
			
		||||
            foreach (array_values($this->context) as $context) {
 | 
			
		||||
                $c[] = $context;
 | 
			
		||||
            }
 | 
			
		||||
            $return['@context'] = $c;
 | 
			
		||||
        }
 | 
			
		||||
        if (sizeof($this->contexts) > 0) {
 | 
			
		||||
            if (array_key_exists('@context', $return)) {
 | 
			
		||||
                $return['@context'] =  [$return['@context']];
 | 
			
		||||
            } else {
 | 
			
		||||
                $return['@context'] =  [];
 | 
			
		||||
            }
 | 
			
		||||
            $return['@context'][] = $this->contexts;
 | 
			
		||||
        }
 | 
			
		||||
        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
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setUUID($id)
 | 
			
		||||
    {
 | 
			
		||||
        $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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								php/federator/data/activitypub/common/article.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								php/federator/data/activitypub/common/article.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Article extends APObject
 | 
			
		||||
{
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct("Article");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create object from json
 | 
			
		||||
     * @param mixed $json input
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        return parent::fromJson($json);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								php/federator/data/activitypub/common/collection.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								php/federator/data/activitypub/common/collection.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,68 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Collection extends APObject
 | 
			
		||||
{
 | 
			
		||||
    protected int $totalItems = 0;
 | 
			
		||||
    private string $first = '';
 | 
			
		||||
    private string $last = '';
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct('Collection');
 | 
			
		||||
        parent::addContext('https://www.w3.org/ns/activitystreams');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * convert internal state to php array
 | 
			
		||||
     * @return array<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    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<string,mixed> $json input json
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										43
									
								
								php/federator/data/activitypub/common/create.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								php/federator/data/activitypub/common/create.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Create extends Activity
 | 
			
		||||
{
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct('Create');
 | 
			
		||||
        parent::addContext('https://www.w3.org/ns/activitystreams');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * convert internal state to php array
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    public function toObject()
 | 
			
		||||
    {
 | 
			
		||||
        $return = parent::toObject();
 | 
			
		||||
        $return['type'] = 'Create';
 | 
			
		||||
        // overwrite id from url
 | 
			
		||||
        $return['id'] = $this->getURL();
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
     * create object from json
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string,mixed> $json input json
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        return parent::fromJson($json);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								php/federator/data/activitypub/common/image.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								php/federator/data/activitypub/common/image.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,62 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Image extends APObject
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * url
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $url
 | 
			
		||||
     */
 | 
			
		||||
    private $url = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * media type
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $mediaType
 | 
			
		||||
     */
 | 
			
		||||
    private $mediaType = '';
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct("Image");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set media type
 | 
			
		||||
     * @param string $mediaType media type
 | 
			
		||||
     * @return Image current instance
 | 
			
		||||
     */
 | 
			
		||||
    public function setMediaType(string $mediaType)
 | 
			
		||||
    {
 | 
			
		||||
        $this->mediaType = $mediaType;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create object from json
 | 
			
		||||
     * @param mixed $json input
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								php/federator/data/activitypub/common/note.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								php/federator/data/activitypub/common/note.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,95 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Note extends APObject
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * sender
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $sender
 | 
			
		||||
     */
 | 
			
		||||
    private $sender = "";
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * receiver
 | 
			
		||||
     *
 | 
			
		||||
     * @var string $receiver
 | 
			
		||||
     */
 | 
			
		||||
    private $receiver = "";
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct("Note");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set sender
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $sender note sender
 | 
			
		||||
     * @return Note current instance
 | 
			
		||||
     */
 | 
			
		||||
    public function setSender(string $sender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->sender = $sender;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get sender
 | 
			
		||||
     *
 | 
			
		||||
     * @return string sender
 | 
			
		||||
     */
 | 
			
		||||
    public function getSender()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->sender;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set receiver
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $receiver note receiver
 | 
			
		||||
     * @return Note current instance
 | 
			
		||||
     */
 | 
			
		||||
    public function setReceiver(string $receiver)
 | 
			
		||||
    {
 | 
			
		||||
        $this->receiver = $receiver;
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * convert internal state to php array
 | 
			
		||||
     * @return array<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    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
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        if (!parent::fromJson($json)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $this->receiver = "";
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								php/federator/data/activitypub/common/orderedcollection.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								php/federator/data/activitypub/common/orderedcollection.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class OrderedCollection extends Collection
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * nested items
 | 
			
		||||
     *
 | 
			
		||||
     * @var APObject[]
 | 
			
		||||
     */
 | 
			
		||||
    protected $items = [];
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        parent::addContext('https://www.w3.org/ns/activitystreams');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * convert internal state to php array
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    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<string,mixed> $json input json
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        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
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setItems(&$items)
 | 
			
		||||
    {
 | 
			
		||||
        $this->items = $items;
 | 
			
		||||
        $this->totalItems = sizeof($items);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class OrderedCollectionPage extends OrderedCollection
 | 
			
		||||
{
 | 
			
		||||
    private string $next = '';
 | 
			
		||||
    private string $prev = '';
 | 
			
		||||
    private string $partOf = '';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        parent::addContext('https://www.w3.org/ns/activitystreams');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * convert internal state to php array
 | 
			
		||||
     *
 | 
			
		||||
     * @return array<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    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['type'] = 'OrderedCollectionPage';
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create object from json
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string,mixed> $json input json
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        return parent::fromJson($json);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set next url
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $url new next URL
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setNext($url)
 | 
			
		||||
    {
 | 
			
		||||
        $this->next = $url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set prev url
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $url new prev URL
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function setPrev($url)
 | 
			
		||||
    {
 | 
			
		||||
        $this->prev = $url;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setPartOf(string $url) : void
 | 
			
		||||
    {
 | 
			
		||||
        $this->partOf = $url;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								php/federator/data/activitypub/common/outbox.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								php/federator/data/activitypub/common/outbox.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,50 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Outbox extends OrderedCollectionPage
 | 
			
		||||
{
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct();
 | 
			
		||||
        parent::addContext('https://www.w3.org/ns/activitystreams');
 | 
			
		||||
        parent::addContexts([
 | 
			
		||||
            "ostatus" => "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<string,mixed>
 | 
			
		||||
     */
 | 
			
		||||
    public function toObject()
 | 
			
		||||
    {
 | 
			
		||||
        $return = parent::toObject();
 | 
			
		||||
        return $return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create object from json
 | 
			
		||||
     *
 | 
			
		||||
     * @param array<string,mixed> $json input json
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        return parent::fromJson($json);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								php/federator/data/activitypub/common/tag.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								php/federator/data/activitypub/common/tag.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,34 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub\Common;
 | 
			
		||||
 | 
			
		||||
class Tag extends APObject
 | 
			
		||||
{
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        parent::__construct("Tag");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * fill object from json
 | 
			
		||||
     *
 | 
			
		||||
     * @param mixed $json input
 | 
			
		||||
     * @return bool true on success
 | 
			
		||||
     */
 | 
			
		||||
    public function fromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        if (!parent::fromJson($json)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        if (array_key_exists('type', $json)) {
 | 
			
		||||
            $this->setType($json['type']);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										108
									
								
								php/federator/data/activitypub/factory.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								php/federator/data/activitypub/factory.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,108 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\Data\ActivityPub;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Factory class for creating various ActivityPub classes
 | 
			
		||||
 */
 | 
			
		||||
class Factory
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create object tree from json
 | 
			
		||||
     * @param array<string, mixed> $json input json
 | 
			
		||||
     * @return Common\APObject|null object or false on error
 | 
			
		||||
     */
 | 
			
		||||
    public 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 null;
 | 
			
		||||
        }
 | 
			
		||||
        if (!array_key_exists('type', $json)) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        $return = null;
 | 
			
		||||
        switch ($json['type']) {
 | 
			
		||||
            case 'Article':
 | 
			
		||||
                $return = new Common\Article();
 | 
			
		||||
                break;
 | 
			
		||||
            /*case 'Document':
 | 
			
		||||
                $return = new Common\Document();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Event':
 | 
			
		||||
                $return = new Common\Event();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Follow':
 | 
			
		||||
                $return = new Common\Follow();
 | 
			
		||||
                break;*/
 | 
			
		||||
            case 'Image':
 | 
			
		||||
                $return = new Common\Image();
 | 
			
		||||
                break;
 | 
			
		||||
            /*case 'Note':
 | 
			
		||||
                $return = new Common\Note();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Question':
 | 
			
		||||
                $return = new \Common\Question();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Video':
 | 
			
		||||
                $return = new \Common\Video();
 | 
			
		||||
                break;*/
 | 
			
		||||
            default:
 | 
			
		||||
                error_log("newFromJson: unknown type: '" . $json['type'] . "' " . $jsonstring);
 | 
			
		||||
                error_log(print_r($json, true));
 | 
			
		||||
        }
 | 
			
		||||
        if ($return !== null && $return->fromJson($json)) {
 | 
			
		||||
            return $return;
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * create object tree from json
 | 
			
		||||
     * @param array<string, mixed> $json input json
 | 
			
		||||
     * @return Common\Activity|false object or false on error
 | 
			
		||||
     */
 | 
			
		||||
    public static function newActivityFromJson($json)
 | 
			
		||||
    {
 | 
			
		||||
        if (!array_key_exists('type', $json)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        //$return = false;
 | 
			
		||||
        switch ($json['type']) {
 | 
			
		||||
            case 'MakePhanHappy':
 | 
			
		||||
                break;
 | 
			
		||||
/*            case 'Accept':
 | 
			
		||||
                $return = new Common\Accept();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Announce':
 | 
			
		||||
                $return = new Common\Announce();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Create':
 | 
			
		||||
                $return = new Common\Create();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Delete':
 | 
			
		||||
                $return = new Common\Delete();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Follow':
 | 
			
		||||
                $return = new Common\Follow();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'Undo':
 | 
			
		||||
                $return = new \Common\Undo();
 | 
			
		||||
                break;*/
 | 
			
		||||
            default:
 | 
			
		||||
                error_log("newActivityFromJson " . print_r($json, true));
 | 
			
		||||
        }
 | 
			
		||||
        /*if ($return !== false && $return->fromJson($json) !== null) {
 | 
			
		||||
            return $return;
 | 
			
		||||
        }*/
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										59
									
								
								php/federator/dio/posts.php
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								php/federator/dio/posts.php
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
<?php
 | 
			
		||||
/**
 | 
			
		||||
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 | 
			
		||||
 * SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator\DIO;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * IO functions related to users
 | 
			
		||||
 */
 | 
			
		||||
class Posts
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get posts by user
 | 
			
		||||
     *
 | 
			
		||||
     * @param \mysqli $dbh @unused-param
 | 
			
		||||
     *          database handle
 | 
			
		||||
     * @param string $id
 | 
			
		||||
     *          user id
 | 
			
		||||
     * @param \Federator\Connector\Connector $connector
 | 
			
		||||
     *          connector to fetch use with
 | 
			
		||||
     * @param \Federator\Cache\Cache|null $cache
 | 
			
		||||
     *          optional caching service
 | 
			
		||||
     * @param string $minId
 | 
			
		||||
     *          minimum ID
 | 
			
		||||
     * @param string $maxId
 | 
			
		||||
     *          maximum ID
 | 
			
		||||
     * @return \Federator\Data\ActivityPub\Common\APObject[]
 | 
			
		||||
     */
 | 
			
		||||
    public static function getPostsByUser($dbh, $id, $connector, $cache, $minId, $maxId)
 | 
			
		||||
    {
 | 
			
		||||
        // ask cache
 | 
			
		||||
        if ($cache !== null) {
 | 
			
		||||
            $posts = $cache->getRemotePostsByUser($id, $minId, $maxId);
 | 
			
		||||
            if ($posts !== false) {
 | 
			
		||||
                return $posts;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        $posts = [];
 | 
			
		||||
        // TODO: check our db
 | 
			
		||||
 | 
			
		||||
        if ($posts === []) {
 | 
			
		||||
            // ask connector for user-id
 | 
			
		||||
            $posts = $connector->getRemotePostsByUser($id, $minId, $maxId);
 | 
			
		||||
            if ($posts === false) {
 | 
			
		||||
                $posts = [];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // save posts to DB
 | 
			
		||||
        if ($cache !== null) {
 | 
			
		||||
            $cache->saveRemotePostsByUser($id, $posts);
 | 
			
		||||
        }
 | 
			
		||||
        return $posts;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +44,8 @@ class User
 | 
			
		|||
            $public = openssl_pkey_get_details($private_key)['key'];
 | 
			
		||||
            $private = '';
 | 
			
		||||
            openssl_pkey_export($private_key, $private);
 | 
			
		||||
            $sql = 'insert into users (id, externalid, rsapublic, rsaprivate, validuntil, type, name, summary, registered, iconmediatype, iconurl, imagemediatype, imageurl)';
 | 
			
		||||
            $sql = 'insert into users (id, externalid, rsapublic, rsaprivate, validuntil,';
 | 
			
		||||
            $sql .= ' type, name, summary, registered, iconmediatype, iconurl, imagemediatype, imageurl)';
 | 
			
		||||
            $sql .= ' values (?, ?, ?, ?, now() + interval 1 day, ?, ?, ?, ?, ?, ?, ?, ?)';
 | 
			
		||||
            $stmt = $dbh->prepare($sql);
 | 
			
		||||
            if ($stmt === false) {
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,8 @@ class User
 | 
			
		|||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            // update to existing user
 | 
			
		||||
            $sql = 'update users set validuntil=now() + interval 1 day, type=?, name=?, summary=?, registered=?, iconmediatype=?, iconurl=?, imagemediatype=?, imageurl=? where id=?';
 | 
			
		||||
            $sql = 'update users set validuntil=now() + interval 1 day, type=?, name=?, summary=?, registered=?,';
 | 
			
		||||
            $sql .= ' iconmediatype=?, iconurl=?, imagemediatype=?, imageurl=? where id=?';
 | 
			
		||||
            $stmt = $dbh->prepare($sql);
 | 
			
		||||
            if ($stmt === false) {
 | 
			
		||||
                throw new \Federator\Exceptions\ServerError();
 | 
			
		||||
| 
						 | 
				
			
			@ -151,7 +153,8 @@ class User
 | 
			
		|||
            return $user;
 | 
			
		||||
        }
 | 
			
		||||
        // check our db
 | 
			
		||||
        $sql = 'select id,externalid,type,name,summary,unix_timestamp(registered),rsapublic,iconmediatype,iconurl,imagemediatype,imageurl from users where id=? and validuntil>=now()';
 | 
			
		||||
        $sql = 'select id,externalid,type,name,summary,unix_timestamp(registered),rsapublic,';
 | 
			
		||||
        $sql .= 'iconmediatype,iconurl,imagemediatype,imageurl from users where id=? and validuntil>=now()';
 | 
			
		||||
        $stmt = $dbh->prepare($sql);
 | 
			
		||||
        if ($stmt === false) {
 | 
			
		||||
            throw new \Federator\Exceptions\ServerError();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,8 +96,8 @@ class Language
 | 
			
		|||
            if ($root === '') {
 | 
			
		||||
                $root = '.';
 | 
			
		||||
            }
 | 
			
		||||
            if (@file_exists($root . '/../lang/' . $this->uselang . "/$group.inc")) {
 | 
			
		||||
                require($root . '/../lang/' . $this->uselang . "/$group.inc");
 | 
			
		||||
            if (@file_exists($root . '../lang/federator/' . $this->uselang . "/$group.inc")) {
 | 
			
		||||
                require($root . '../lang/federator/' . $this->uselang . "/$group.inc");
 | 
			
		||||
                $this->lang[$group] = $l;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,8 +5,12 @@
 | 
			
		|||
 *
 | 
			
		||||
 * @author Sascha Nitsch (grumpydeveloper)
 | 
			
		||||
 **/
 | 
			
		||||
 | 
			
		||||
namespace Federator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * maintenance functions
 | 
			
		||||
 */
 | 
			
		||||
class Maintenance
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,13 @@ class ContentNation implements Connector
 | 
			
		|||
     */
 | 
			
		||||
    private $config;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * main instance
 | 
			
		||||
     *
 | 
			
		||||
     * @var \Federator\Main $main
 | 
			
		||||
     */
 | 
			
		||||
    private $main;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * service-URL
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -30,11 +37,102 @@ class ContentNation implements Connector
 | 
			
		|||
    /**
 | 
			
		||||
     * constructor
 | 
			
		||||
     *
 | 
			
		||||
     * @param \Federator\Main $main
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    public function __construct($main)
 | 
			
		||||
    {
 | 
			
		||||
        $config = parse_ini_file($_SERVER['DOCUMENT_ROOT'] . '../contentnation.ini');
 | 
			
		||||
        $this->service = $config['service-uri'];
 | 
			
		||||
        $config = parse_ini_file($_SERVER['DOCUMENT_ROOT'] . '../contentnation.ini', true);
 | 
			
		||||
        if ($config !== false) {
 | 
			
		||||
            $this->config = $config;
 | 
			
		||||
        }
 | 
			
		||||
        $this->service = $config['contentnation']['service-uri'];
 | 
			
		||||
        $this->main = $main;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get posts by given user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $userId user id
 | 
			
		||||
     * @param string $min min date
 | 
			
		||||
     * @param string $max max date
 | 
			
		||||
     * @return \Federator\Data\ActivityPub\Common\APObject[]|false
 | 
			
		||||
     */
 | 
			
		||||
    public function getRemotePostsByUser($userId, $min, $max)
 | 
			
		||||
    {
 | 
			
		||||
        $remoteURL = $this->service . '/api/profile/' . $userId . '/activities';
 | 
			
		||||
        if ($min !== '') {
 | 
			
		||||
            $remoteURL .= '&minTS=' . urlencode($min);
 | 
			
		||||
        }
 | 
			
		||||
        if ($max !== '') {
 | 
			
		||||
            $remoteURL .= '&maxTS=' . urlencode($max);
 | 
			
		||||
        }
 | 
			
		||||
        [$response, $info] = \Federator\Main::getFromRemote($remoteURL, []);
 | 
			
		||||
        if ($info['http_code'] != 200) {
 | 
			
		||||
            print_r($info);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $r = json_decode($response, true);
 | 
			
		||||
        if ($r === false || $r === null || !is_array($r)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $posts = [];
 | 
			
		||||
        if (array_key_exists('articles', $r)) {
 | 
			
		||||
            $articles = $r['articles'];
 | 
			
		||||
            $host = $_SERVER['SERVER_NAME'];
 | 
			
		||||
            $imgpath = $this->config['userdata']['path'];
 | 
			
		||||
            $userdata = $this->config['userdata']['url'];
 | 
			
		||||
            foreach ($articles as $article) {
 | 
			
		||||
                $create = new \Federator\Data\ActivityPub\Common\Create();
 | 
			
		||||
                $create->setAActor('https://' . $host .'/' . $article['profilename']);
 | 
			
		||||
                $create->setID($article['id'])
 | 
			
		||||
                    ->setURL('https://'.$host.'/' . $article['profilename']
 | 
			
		||||
                        . '/statuses/' . $article['id'] . '/activity')
 | 
			
		||||
                    ->setPublished(max($article['published'], $article['modified']))
 | 
			
		||||
                    ->addTo("https://www.w3.org/ns/activitystreams#Public")
 | 
			
		||||
                    ->addCC('https://' . $host . '/' . $article['profilename'] . '/followers.json');
 | 
			
		||||
                $apArticle = new \Federator\Data\ActivityPub\Common\Article();
 | 
			
		||||
                if (array_key_exists('tags', $article)) {
 | 
			
		||||
                    foreach ($article['tags'] as $tag) {
 | 
			
		||||
                        $href = 'https://' . $host . '/' . $article['language']
 | 
			
		||||
                            . '/search.htm?tagsearch=' . urlencode($tag);
 | 
			
		||||
                        $tagObj = new \Federator\Data\ActivityPub\Common\Tag();
 | 
			
		||||
                        $tagObj->setHref($href)
 | 
			
		||||
                            ->setName('#' . urlencode(str_replace(' ', '', $tag)))
 | 
			
		||||
                            ->setType('Hashtag');
 | 
			
		||||
                        $article->addTag($tagObj);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                $apArticle->setPublished($article['published'])
 | 
			
		||||
                    ->setName($article['title'])
 | 
			
		||||
                    ->setAttributedTo('https://' . $host .'/' . $article['profilename'])
 | 
			
		||||
                    ->setContent(
 | 
			
		||||
                        $article['teaser'] ??
 | 
			
		||||
                            $this->main->translate(
 | 
			
		||||
                                $article['language'],
 | 
			
		||||
                                'article',
 | 
			
		||||
                                'newarticle'
 | 
			
		||||
                            )
 | 
			
		||||
                    )
 | 
			
		||||
                    ->addTo("https://www.w3.org/ns/activitystreams#Public")
 | 
			
		||||
                    ->addCC('https://' . $host . '/' . $article['profilename'] . '/followers.json');
 | 
			
		||||
                $articleimage = $article['imagealt']  ??
 | 
			
		||||
                    $this->main->translate($article['language'], 'article', 'image');
 | 
			
		||||
                $idurl = 'https://' . $host . '/' . $article['language']
 | 
			
		||||
                    . '/' . $article['profilename'] . '/'. $article['name'];
 | 
			
		||||
                $apArticle->setID($idurl)
 | 
			
		||||
                    ->setURL($idurl);
 | 
			
		||||
                $image = $article['image'] !== "" ? $article['image'] : $article['profileimg'];
 | 
			
		||||
                $mediaType = @mime_content_type($imgpath . $article['profile'] . '/' . $image) | 'text/plain';
 | 
			
		||||
                $img = new \Federator\Data\ActivityPub\Common\Image();
 | 
			
		||||
                $img->setMediaType($mediaType)
 | 
			
		||||
                    ->setName($articleimage)
 | 
			
		||||
                    ->setURL($userdata . $article['profile'] . '/' . $image);
 | 
			
		||||
                $apArticle->addImage($img);
 | 
			
		||||
                $create->setObject($apArticle);
 | 
			
		||||
                $posts[] = $create;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return $posts;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +145,6 @@ class ContentNation implements Connector
 | 
			
		|||
        $remoteURL = $this->service . '/api/stats';
 | 
			
		||||
        [$response, $info] = \Federator\Main::getFromRemote($remoteURL, []);
 | 
			
		||||
        if ($info['http_code'] != 200) {
 | 
			
		||||
            print_r($info);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        $r = json_decode($response, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -147,6 +244,6 @@ namespace Federator;
 | 
			
		|||
 */
 | 
			
		||||
function contentnation_load($main)
 | 
			
		||||
{
 | 
			
		||||
    $cn = new Connector\ContentNation();
 | 
			
		||||
    $cn = new Connector\ContentNation($main);
 | 
			
		||||
    $main->setConnector($cn);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,19 @@ class DummyConnector implements Connector
 | 
			
		|||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get posts by given user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $id user id @unused-param
 | 
			
		||||
     * @param string $minId min ID @unused-param
 | 
			
		||||
     * @param string $maxId max ID @unused-param
 | 
			
		||||
     * @return \Federator\Data\ActivityPub\Common\APObject[]|false
 | 
			
		||||
     */
 | 
			
		||||
    public function getRemotePostsByUser($id, $minId, $maxId)
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get statistics from remote system
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,6 +77,21 @@ class RedisCache implements Cache
 | 
			
		|||
        return $prefix . '_' . md5($input);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get posts by given user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $id user id @unused-param
 | 
			
		||||
     * @param string $minId min ID @unused-param
 | 
			
		||||
     * @param string $maxId max ID @unused-param
 | 
			
		||||
 | 
			
		||||
     * @return \Federator\Data\ActivityPub\Common\APObject[]|false
 | 
			
		||||
     */
 | 
			
		||||
    public function getRemotePostsByUser($id, $minId, $maxId)
 | 
			
		||||
    {
 | 
			
		||||
        error_log("rediscache::getRemotePostsByUser not implemented");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * get statistics from remote system
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -137,6 +152,18 @@ class RedisCache implements Cache
 | 
			
		|||
        return $user;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * save remote posts by user
 | 
			
		||||
     *
 | 
			
		||||
     * @param string $user user name @unused-param
 | 
			
		||||
     * @param \Federator\Data\ActivityPub\Common\APObject[]|false $posts user posts @unused-param
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function saveRemotePostsByUser($user, $posts)
 | 
			
		||||
    {
 | 
			
		||||
        error_log("rediscache::saveRemotePostsByUser not implemented");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * save remote stats
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
{ldelim}
 | 
			
		||||
  "subject": "acct:{$username}@{$domain}",
 | 
			
		||||
  "aliases": [
 | 
			
		||||
    "https://{$domain}/@{$username}"
 | 
			
		||||
    "https://{$domain}/@{$username}",
 | 
			
		||||
    "https://{$domain}/users/{$username}"
 | 
			
		||||
  ],
 | 
			
		||||
  "links": [
 | 
			
		||||
| 
						 | 
				
			
			@ -11,4 +11,4 @@
 | 
			
		|||
{/if}
 | 
			
		||||
    {ldelim}"rel": "http://ostatus.org/schema/1.0/subscribe", "template": "https://{$domain}/authorize_interaction?uri={ldelim}uri{rdelim}"{rdelim}
 | 
			
		||||
  ]
 | 
			
		||||
{rdelim}
 | 
			
		||||
{rdelim}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue