Make the library PHP ^5.5 compatible
This commit is contained in:
parent
9c4c39fb0b
commit
1b5003727d
108
composer.json
108
composer.json
@ -1,54 +1,60 @@
|
||||
{
|
||||
"name": "pterotype/activitypub-php",
|
||||
"description": "An ActivityPub library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeremy Dormitzer",
|
||||
"email": "jeremy@dormitzer.net",
|
||||
"homepage": "https://jeremydormitzer.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "phpunit -c ./test/config.xml test",
|
||||
"test-debug": "XDEBUG_CONFIG='idekey=ap_session' php ./vendor/bin/phpunit test",
|
||||
"docs": "phpdoc -d ./src -t ./docs"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.friendi.ca/friendica/php-json-ld"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"doctrine/orm": "^2.6",
|
||||
"friendica/json-ld": "^1.1",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"phpseclib/phpseclib": "^2.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"symfony/dependency-injection": "^4.2",
|
||||
"symfony/http-kernel": "^4.2",
|
||||
"symfony/psr-http-message-bridge": "^1.1",
|
||||
"zendframework/zend-diactoros": "^1.8",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/dbunit": "^2.0",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ActivityPub\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"ActivityPub\\Test\\": "test/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
"name": "pterotype/activitypub-php",
|
||||
"description": "An ActivityPub library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jeremy Dormitzer",
|
||||
"email": "jeremy@dormitzer.net",
|
||||
"homepage": "https://jeremydormitzer.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"test": "phpunit -c ./test/config.xml test",
|
||||
"test-debug": "XDEBUG_CONFIG='idekey=ap_session' php ./vendor/bin/phpunit test",
|
||||
"docs": "phpdoc -d ./src -t ./docs"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://git.friendi.ca/friendica/php-json-ld"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"doctrine/annotations": "1.2.7",
|
||||
"doctrine/cache": "1.6.2",
|
||||
"doctrine/common": "2.6.2",
|
||||
"doctrine/instantiator": "1.0.5",
|
||||
"doctrine/orm": "2.5.14",
|
||||
"friendica/json-ld": "^1.1",
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"phpseclib/phpseclib": "^2.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"symfony/dependency-injection": "^3.4",
|
||||
"symfony/event-dispatcher": "^3.4",
|
||||
"symfony/http-foundation": "^3.4",
|
||||
"symfony/http-kernel": "^3.4",
|
||||
"symfony/psr-http-message-bridge": "^1.1",
|
||||
"zendframework/zend-diactoros": "1.4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/dbunit": "^2.0",
|
||||
"phpunit/phpunit": "^4.0",
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ActivityPub\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"ActivityPub\\Test\\": "test/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
|
698
composer.lock
generated
698
composer.lock
generated
File diff suppressed because it is too large
Load Diff
81
src/Activities/AcceptHandler.php
Normal file
81
src/Activities/AcceptHandler.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Objects\CollectionsService;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
class AcceptHandler implements EventSubscriberInterface
|
||||
{
|
||||
/**
|
||||
* @var ObjectsService
|
||||
*/
|
||||
private $objectsService;
|
||||
|
||||
/**
|
||||
* @var CollectionsService
|
||||
*/
|
||||
private $collectionsService;
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return array(
|
||||
InboxActivityEvent::NAME => 'handleInbox',
|
||||
OutboxActivityEvent::NAME => 'handleOutbox',
|
||||
);
|
||||
}
|
||||
|
||||
public function __construct( ObjectsService $objectsService,
|
||||
CollectionsService $collectionsService )
|
||||
{
|
||||
$this->objectsService = $objectsService;
|
||||
$this->collectionsService = $collectionsService;
|
||||
}
|
||||
|
||||
public function handleInbox( InboxActivityEvent $event )
|
||||
{
|
||||
$activity = $event->getActivity();
|
||||
if ( $activity['type'] !== 'Accept' ) {
|
||||
return;
|
||||
}
|
||||
// add to following collection
|
||||
}
|
||||
|
||||
public function handleOutbox( OutboxActivityEvent $event )
|
||||
{
|
||||
$activity = $event->getActivity();
|
||||
if ( $activity['type'] !== 'Accept' ) {
|
||||
return;
|
||||
}
|
||||
$request = $event->getRequest();
|
||||
// either there is a 'follow' key on the request,
|
||||
// in which case this is an auto-accept dispatched from
|
||||
// the FollowHandler so the Follow won't be in the database yet,
|
||||
// or there isn't, in which case this is an ordinary Accept
|
||||
// sent by a client and the Follow is in the database
|
||||
$follow = $request->attributes->get( 'follow' );
|
||||
if ( ! $follow ) {
|
||||
$followId = $activity['object'];
|
||||
if ( is_array( $followId ) && array_key_exists( 'id', $followId ) ) {
|
||||
$followId = $followId['id'];
|
||||
}
|
||||
if ( ! is_string( $followId ) ) {
|
||||
return;
|
||||
}
|
||||
$follow = $this->objectsService->dereference( $followId )->asArray( -1 );
|
||||
}
|
||||
if ( ! $follow || ! array_key_exists( 'object', $follow ) ) {
|
||||
return;
|
||||
}
|
||||
$followObjectId = $follow['object'];
|
||||
if ( is_array( $followObjectId ) && array_key_exists( 'id', $followObjectId ) ) {
|
||||
$followObjectId = $followObjectId['id'];
|
||||
}
|
||||
$actor = $event->getActor();
|
||||
if ( $followObjectId !== $actor['id'] ) {
|
||||
return;
|
||||
}
|
||||
$this->collectionsService->addItem( $actor['followers'], $activity['actor'] );
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\ActivityEvent;
|
||||
use ActivityPub\Activities\InboxActivityEvent;
|
||||
use ActivityPub\Activities\OutboxActivityEvent;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Utils\DateTimeProvider;
|
||||
use DateTime;
|
||||
|
@ -1,10 +1,7 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\InboxActivityEvent;
|
||||
use ActivityPub\Activities\OutboxActivityEvent;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use GuzzleHttp\Client;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -35,9 +32,11 @@ class FollowHandler implements EventSubscriberInterface
|
||||
$this->contextProvider = $contextProvider;
|
||||
}
|
||||
|
||||
public function handleInbox( InboxActivityEvent $event,
|
||||
$eventName,
|
||||
EventDispatcher $eventDispatcher )
|
||||
|
||||
public function handleInbox(InboxActivityEvent $event,
|
||||
/** @noinspection PhpUnusedParameterInspection */
|
||||
$eventName,
|
||||
EventDispatcher $eventDispatcher )
|
||||
{
|
||||
$activity = $event->getActivity();
|
||||
if ( ! $activity['type'] === 'Follow' ) {
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\ActivityEvent;
|
||||
|
||||
class InboxActivityEvent extends ActivityEvent
|
||||
{
|
||||
const NAME = 'inbox.activity';
|
||||
|
@ -1,11 +1,9 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\OutboxActivityEvent;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* The NonActivityHandler wraps non-activity objects sent to the outbox in a
|
||||
@ -49,22 +47,20 @@ class NonActivityHandler implements EventSubscriberInterface
|
||||
if ( in_array( $object['type'], self::activityTypes() ) ) {
|
||||
return;
|
||||
}
|
||||
$request = $event->getRequest();
|
||||
$actor = $event->getActor();
|
||||
$create = $this->makeCreate( $request, $object, $actor );
|
||||
$create = $this->makeCreate( $object, $actor );
|
||||
$event->setActivity( $create );
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a new Create activity with $object as the object
|
||||
*
|
||||
* @param Request $request The current request
|
||||
* @param array $object The object
|
||||
* @param ActivityPubObject $actorId The actor creating the object
|
||||
* @param ActivityPubObject $actor The actor creating the object
|
||||
*
|
||||
* @return array The Create activity
|
||||
*/
|
||||
private function makeCreate( Request $request, array $object,
|
||||
private function makeCreate( array $object,
|
||||
ActivityPubObject $actor )
|
||||
{
|
||||
$create = array(
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\ActivityEvent;
|
||||
|
||||
class OutboxActivityEvent extends ActivityEvent
|
||||
{
|
||||
const NAME = 'outbox.activity';
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\InboxActivityEvent;
|
||||
use ActivityPub\Activities\OutboxActivityEvent;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Activities;
|
||||
|
||||
use ActivityPub\Activities\InboxActivityEvent;
|
||||
use ActivityPub\Activities\OutboxActivityEvent;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Auth;
|
||||
|
||||
use Exception;
|
||||
@ -40,7 +41,7 @@ class AuthListener implements EventSubscriberInterface
|
||||
* Constructs a new AuthenticationService
|
||||
*
|
||||
* @param Callable $authFunction A Callable that should accept
|
||||
*
|
||||
* @param ObjectsService $objectsService
|
||||
*/
|
||||
public function __construct( Callable $authFunction, ObjectsService $objectsService )
|
||||
{
|
||||
|
@ -42,6 +42,7 @@ class SignatureListener implements EventSubscriberInterface
|
||||
* Check for a valid HTTP signature on the request. If the request has a valid
|
||||
* signature, set the 'signed' and 'signedBy' keys on the request ('signedBy' is
|
||||
* the id of the actor whose key signed the request)
|
||||
* @param GetResponseEvent $event
|
||||
*/
|
||||
public function validateHttpSignature( GetResponseEvent $event )
|
||||
{
|
||||
|
@ -1,9 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Config;
|
||||
|
||||
use ActivityPub\Config\ActivityPubConfigBuilder;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
|
||||
/**
|
||||
* The ActivityPubConfig is a data class to hold ActivityPub configuration options
|
||||
*/
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Config;
|
||||
|
||||
use ActivityPub\Config\ActivityPubConfig;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use ActivityPub\Objects\IdProvider;
|
||||
use Exception;
|
||||
|
@ -1,4 +1,7 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Config;
|
||||
|
||||
use ActivityPub\Activities\CreateHandler;
|
||||
@ -11,7 +14,6 @@ use ActivityPub\Auth\AuthService;
|
||||
use ActivityPub\Auth\SignatureListener;
|
||||
use ActivityPub\Controllers\GetController;
|
||||
use ActivityPub\Controllers\PostController;
|
||||
use ActivityPub\Config\ActivityPubConfig;
|
||||
use ActivityPub\Crypto\HttpSignatureService;
|
||||
use ActivityPub\Database\PrefixNamingStrategy;
|
||||
use ActivityPub\Http\Router;
|
||||
|
@ -65,7 +65,8 @@ class GetController
|
||||
if ( $object->hasField( 'type' ) &&
|
||||
( $object['type'] === 'Collection' ||
|
||||
$object['type'] === 'OrderedCollection' ) ) {
|
||||
return $this->collectionsService->pageAndFilterCollection( $request, $object );
|
||||
$pagedCollection = $this->collectionsService->pageAndFilterCollection( $request, $object );
|
||||
return new JsonResponse( $pagedCollection );
|
||||
}
|
||||
$response = new JsonResponse( $object->asArray() );
|
||||
if ( $object->hasField( 'type' ) &&
|
||||
|
@ -7,6 +7,7 @@ use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@ -40,6 +41,7 @@ class PostController
|
||||
* Either dispatches an inbox/outbox activity event or throws the appropriate
|
||||
* HTTP error.
|
||||
* @param Request $request The request
|
||||
* @return Response
|
||||
*/
|
||||
public function handle( Request $request )
|
||||
{
|
||||
@ -112,15 +114,6 @@ class PostController
|
||||
return true;
|
||||
}
|
||||
|
||||
private function objectWithField( $name, $value )
|
||||
{
|
||||
$results = $this->objectsService->query( array( $name => $value ) );
|
||||
if ( count( $results ) === 0 ) {
|
||||
return false;
|
||||
}
|
||||
return $results[0];
|
||||
}
|
||||
|
||||
private function getUriWithoutQuery( Request $request )
|
||||
{
|
||||
$uri = $request->getUri();
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?php
|
||||
namespace ActivityPub\Crypto;
|
||||
|
||||
use ActivityPub\Utils\HeaderUtils;
|
||||
use DateTime;
|
||||
use ActivityPub\Utils\DateTimeProvider;
|
||||
use ActivityPub\Utils\SimpleDateTimeProvider;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\HeaderUtils;
|
||||
|
||||
/**
|
||||
* The HttpSignatureService provides methods to generate and verify HTTP signatures
|
||||
@ -54,10 +54,10 @@ class HttpSignatureService
|
||||
/**
|
||||
* Generates a signature given the request and private key
|
||||
*
|
||||
* @param RequestInterface $psrRequest The request to be signed
|
||||
* @param RequestInterface $request The request to be signed
|
||||
* @param string $privateKey The private key to use to sign the request
|
||||
* @param string $keyId The id of the signing key
|
||||
* @param array $headers The headers to use in the signature
|
||||
* @param array $headers|null The headers to use in the signature
|
||||
* (default ['(request-target)', 'host', 'date'])
|
||||
* @return string The Signature header value
|
||||
*/
|
||||
@ -70,7 +70,7 @@ class HttpSignatureService
|
||||
$headers = array_map( 'strtolower', $headers );
|
||||
$signingString = $this->getSigningString( $request, $headers );
|
||||
$keypair = RsaKeypair::fromPrivateKey( $privateKey );
|
||||
$signature = base64_encode( $keypair->sign( $signingString, 'rsa256' ) );
|
||||
$signature = base64_encode( $keypair->sign( $signingString, 'sha256' ) );
|
||||
$headersStr = implode( ' ', $headers );
|
||||
return "keyId=\"$keyId\"," .
|
||||
"algorithm=\"rsa-sha256\"," .
|
||||
@ -127,7 +127,7 @@ class HttpSignatureService
|
||||
/**
|
||||
* Returns the signing string from the request
|
||||
*
|
||||
* @param Request $request The request
|
||||
* @param RequestInterface $request The request
|
||||
* @param array $headers The headers to use to generate the signing string
|
||||
* @return string The signing string
|
||||
*/
|
||||
|
@ -65,7 +65,7 @@ class RsaKeypair
|
||||
);
|
||||
}
|
||||
$rsa = new RSA();
|
||||
$rsa->setHash( 'sha256' );
|
||||
$rsa->setHash( $hash );
|
||||
$rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
|
||||
$rsa->loadKey( $this->privateKey );
|
||||
return $rsa->sign( $data );
|
||||
|
@ -1,10 +1,12 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Entities;
|
||||
|
||||
use ArrayAccess;
|
||||
use BadMethodCallException;
|
||||
use DateTime;
|
||||
use ActivityPub\Utils\Util;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
/**
|
||||
@ -137,6 +139,7 @@ class ActivityPubObject implements ArrayAccess
|
||||
/**
|
||||
* Returns true if the object contains a field with key $name
|
||||
*
|
||||
* @param mixed $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasField( $name )
|
||||
@ -171,6 +174,7 @@ class ActivityPubObject implements ArrayAccess
|
||||
* The value is either a string, another ActivityPubObject, or null
|
||||
* if no such key exists.
|
||||
*
|
||||
* @param mixed $name
|
||||
* @return string|ActivityPubObject|null The field's value, or null if
|
||||
* the field is not found
|
||||
*/
|
||||
@ -192,6 +196,7 @@ class ActivityPubObject implements ArrayAccess
|
||||
* $object.
|
||||
*
|
||||
* @param Field $field
|
||||
* @param DateTime|null $time
|
||||
*/
|
||||
public function addField( Field $field, DateTime $time = null )
|
||||
{
|
||||
@ -205,6 +210,7 @@ class ActivityPubObject implements ArrayAccess
|
||||
/**
|
||||
* Returns true if the object is referenced by a field with key $name
|
||||
*
|
||||
* @param mixed $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasReferencingField( $name )
|
||||
|
@ -1,4 +1,7 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Entities;
|
||||
|
||||
use DateTime;
|
||||
@ -82,7 +85,9 @@ class Field
|
||||
* @param ActivityPubObject $object The object to which this field belongs
|
||||
* @param string $name The name of the field
|
||||
* @param string $value The value of the field
|
||||
* @param DateTime|null $time
|
||||
* @return Field The new field
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function withValue( ActivityPubObject $object, $name, $value, DateTime $time = null )
|
||||
{
|
||||
@ -102,7 +107,9 @@ class Field
|
||||
* @param ActivityPubObject $object The object to which this field belongs
|
||||
* @param string $name The name of the field
|
||||
* @param ActivityPubObject $targetObject The object that this field holds
|
||||
* @param DateTime|null $time
|
||||
* @return Field The new field
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function withObject( ActivityPubObject $object,
|
||||
$name,
|
||||
@ -269,6 +276,7 @@ class Field
|
||||
/**
|
||||
* Returns true if $this is equal to $other
|
||||
*
|
||||
* @param Field $other
|
||||
* @return bool
|
||||
*/
|
||||
public function equals( Field $other )
|
||||
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Entities;
|
||||
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
|
||||
/**
|
||||
* The keys table holds the private keys associated with ActivityPub actors
|
||||
*
|
||||
|
@ -1,4 +1,7 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Objects;
|
||||
|
||||
use ActivityPub\Auth\AuthService;
|
||||
@ -56,6 +59,9 @@ class CollectionsService
|
||||
* Returns an array representation of the $collection
|
||||
*
|
||||
* Returns the collection paged and filtered by the request's authorization status
|
||||
* @param Request $request
|
||||
* @param ActivityPubObject $collection
|
||||
* @return array
|
||||
*/
|
||||
public function pageAndFilterCollection( Request $request,
|
||||
ActivityPubObject $collection )
|
||||
@ -125,6 +131,7 @@ class CollectionsService
|
||||
*/
|
||||
public function addItem( ActivityPubObject $collection, array $item )
|
||||
{
|
||||
// TODO implement me
|
||||
if ( ! $collection->hasField( 'items' ) ) {
|
||||
$items = new ActivityPubObject(
|
||||
$this->dateTimeProvider->getTime( 'collections-service.create' )
|
||||
@ -189,7 +196,7 @@ class CollectionsService
|
||||
$idx = $offset;
|
||||
$count = 0;
|
||||
while ( $count < $pageSize ) {
|
||||
$item = $collectionItems->getFieldValue( strval( $idx ) );
|
||||
$item = $collectionItems->getFieldValue( $idx );
|
||||
if ( ! $item ) {
|
||||
break;
|
||||
}
|
||||
@ -225,14 +232,14 @@ class CollectionsService
|
||||
|
||||
private function hasNextItem( Request $request, ActivityPubObject $collectionItems, $idx )
|
||||
{
|
||||
$next = $collectionItems->getFieldValue( strval( $idx ) );
|
||||
$next = $collectionItems->getFieldValue( $idx );
|
||||
while ( $next ) {
|
||||
if ( is_string( $next ) ||
|
||||
$this->authService->isAuthorized( $request, $next ) ) {
|
||||
return $idx;
|
||||
}
|
||||
$idx++;
|
||||
$next = $collectionItems->getFieldValue( strval( $idx ) );
|
||||
$next = $collectionItems->getFieldValue( $idx );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
namespace ActivityPub\Objects;
|
||||
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Utils\RandomProvider;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
|
@ -1,10 +1,11 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Objects;
|
||||
|
||||
use DateTime;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Utils\Util;
|
||||
use ActivityPub\Utils\DateTimeProvider;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
@ -66,17 +67,17 @@ class ObjectsService
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$this->entityManager->flush();
|
||||
return $object;
|
||||
}
|
||||
}/** @noinspection PhpDocMissingThrowsInspection */
|
||||
|
||||
/**
|
||||
* Persists a field.
|
||||
* Persists a field.
|
||||
*
|
||||
* If the field is an array, persist it as a child object
|
||||
*
|
||||
* @param ActivityPubObject $object
|
||||
* @param string $fieldName
|
||||
* @param string|array $fieldValue
|
||||
*
|
||||
* @param string $context
|
||||
*/
|
||||
private function persistField( $object, $fieldName, $fieldValue, $context = 'objects-service.create' )
|
||||
{
|
||||
|
220
src/Utils/HeaderUtils.php
Normal file
220
src/Utils/HeaderUtils.php
Normal file
@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/*
|
||||
* Backported from Symfony 4.1
|
||||
* Original copyright:
|
||||
*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace ActivityPub\Utils;
|
||||
/**
|
||||
* HTTP header utility functions.
|
||||
*
|
||||
* @author Christian Schmidt <github@chsc.dk>
|
||||
*/
|
||||
class HeaderUtils
|
||||
{
|
||||
const DISPOSITION_ATTACHMENT = 'attachment';
|
||||
const DISPOSITION_INLINE = 'inline';
|
||||
/**
|
||||
* This class should not be instantiated.
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
/**
|
||||
* Splits an HTTP header by one or more separators.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* HeaderUtils::split("da, en-gb;q=0.8", ",;")
|
||||
* // => ['da'], ['en-gb', 'q=0.8']]
|
||||
*
|
||||
* @param string $header HTTP header value
|
||||
* @param string $separators List of characters to split on, ordered by
|
||||
* precedence, e.g. ",", ";=", or ",;="
|
||||
*
|
||||
* @return array Nested array with as many levels as there are characters in
|
||||
* $separators
|
||||
*/
|
||||
public static function split($header, $separators)
|
||||
{
|
||||
$quotedSeparators = preg_quote($separators, '/');
|
||||
preg_match_all('
|
||||
/
|
||||
(?!\s)
|
||||
(?:
|
||||
# quoted-string
|
||||
"(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$)
|
||||
|
|
||||
# token
|
||||
[^"'.$quotedSeparators.']+
|
||||
)+
|
||||
(?<!\s)
|
||||
|
|
||||
# separator
|
||||
\s*
|
||||
(?<separator>['.$quotedSeparators.'])
|
||||
\s*
|
||||
/x', trim($header), $matches, PREG_SET_ORDER);
|
||||
return self::groupParts($matches, $separators);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines an array of arrays into one associative array.
|
||||
*
|
||||
* Each of the nested arrays should have one or two elements. The first
|
||||
* value will be used as the keys in the associative array, and the second
|
||||
* will be used as the values, or true if the nested array only contains one
|
||||
* element. Array keys are lowercased.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* HeaderUtils::combine([["foo", "abc"], ["bar"]])
|
||||
* // => ["foo" => "abc", "bar" => true]
|
||||
* @param array $parts
|
||||
* @return array
|
||||
*/
|
||||
public static function combine(array $parts)
|
||||
{
|
||||
$assoc = [];
|
||||
foreach ($parts as $part) {
|
||||
$name = strtolower($part[0]);
|
||||
if (isset($part[1])) {
|
||||
$value = $part[1];
|
||||
} else {
|
||||
$value = true;
|
||||
}
|
||||
$assoc[$name] = $value;
|
||||
}
|
||||
return $assoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins an associative array into a string for use in an HTTP header.
|
||||
*
|
||||
* The key and value of each entry are joined with "=", and all entries
|
||||
* are joined with the specified separator and an additional space (for
|
||||
* readability). Values are quoted if necessary.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",")
|
||||
* // => 'foo=abc, bar, baz="a b c"'
|
||||
* @param array $assoc
|
||||
* @param $separator
|
||||
* @return string
|
||||
*/
|
||||
public static function toString(array $assoc, $separator)
|
||||
{
|
||||
$parts = [];
|
||||
foreach ($assoc as $name => $value) {
|
||||
if (true === $value) {
|
||||
$parts[] = $name;
|
||||
} else {
|
||||
$parts[] = $name.'='.self::quote($value);
|
||||
}
|
||||
}
|
||||
return implode($separator.' ', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes a string as a quoted string, if necessary.
|
||||
*
|
||||
* If a string contains characters not allowed by the "token" construct in
|
||||
* the HTTP specification, it is backslash-escaped and enclosed in quotes
|
||||
* to match the "quoted-string" construct.
|
||||
* @param $s
|
||||
* @return string
|
||||
*/
|
||||
public static function quote($s)
|
||||
{
|
||||
if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) {
|
||||
return $s;
|
||||
}
|
||||
return '"'.addcslashes($s, '"\\"').'"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a quoted string.
|
||||
*
|
||||
* If passed an unquoted string that matches the "token" construct (as
|
||||
* defined in the HTTP specification), it is passed through verbatimly.
|
||||
* @param $s
|
||||
* @return string|string[]|null
|
||||
*/
|
||||
public static function unquote($s)
|
||||
{
|
||||
return preg_replace('/\\\\(.)|"/', '$1', $s);
|
||||
}
|
||||
/**
|
||||
* Generates a HTTP Content-Disposition field-value.
|
||||
*
|
||||
* @param string $disposition One of "inline" or "attachment"
|
||||
* @param string $filename A unicode string
|
||||
* @param string $filenameFallback A string containing only ASCII characters that
|
||||
* is semantically equivalent to $filename. If the filename is already ASCII,
|
||||
* it can be omitted, or just copied from $filename
|
||||
*
|
||||
* @return string A string suitable for use as a Content-Disposition field-value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @see RFC 6266
|
||||
*/
|
||||
public static function makeDisposition($disposition, $filename, $filenameFallback = '')
|
||||
{
|
||||
if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) {
|
||||
throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
|
||||
}
|
||||
if ('' === $filenameFallback) {
|
||||
$filenameFallback = $filename;
|
||||
}
|
||||
// filenameFallback is not ASCII.
|
||||
if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
|
||||
throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
|
||||
}
|
||||
// percent characters aren't safe in fallback.
|
||||
if (false !== strpos($filenameFallback, '%')) {
|
||||
throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
|
||||
}
|
||||
// path separators aren't allowed in either.
|
||||
if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
|
||||
throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
|
||||
}
|
||||
$params = ['filename' => $filenameFallback];
|
||||
if ($filename !== $filenameFallback) {
|
||||
$params['filename*'] = "utf-8''".rawurlencode($filename);
|
||||
}
|
||||
return $disposition.'; '.self::toString($params, ';');
|
||||
}
|
||||
private static function groupParts(array $matches, $separators)
|
||||
{
|
||||
$separator = $separators[0];
|
||||
$partSeparators = substr($separators, 1);
|
||||
$i = 0;
|
||||
$partMatches = [];
|
||||
foreach ($matches as $match) {
|
||||
if (isset($match['separator']) && $match['separator'] === $separator) {
|
||||
++$i;
|
||||
} else {
|
||||
$partMatches[$i][] = $match;
|
||||
}
|
||||
}
|
||||
$parts = [];
|
||||
if ($partSeparators) {
|
||||
foreach ($partMatches as $matches) {
|
||||
$parts[] = self::groupParts($matches, $partSeparators);
|
||||
}
|
||||
} else {
|
||||
foreach ($partMatches as $matches) {
|
||||
$parts[] = self::unquote($matches[0][0]);
|
||||
}
|
||||
}
|
||||
return $parts;
|
||||
}
|
||||
}
|
@ -1,11 +1,12 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Utils;
|
||||
|
||||
use DateTime;
|
||||
use ActivityPub\Utils\DateTimeProvider;
|
||||
|
||||
class SimpleDateTimeProvider implements DateTimeProvider
|
||||
{
|
||||
/** @noinspection PhpDocMissingThrowsInspection */
|
||||
/**
|
||||
* Returns a new DateTime for the given context
|
||||
*
|
||||
|
20
test/Activities/AcceptHandlerTest.php
Normal file
20
test/Activities/AcceptHandlerTest.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace ActivityPub\Test\Activities;
|
||||
|
||||
use ActivityPub\Test\TestConfig\APTestCase;
|
||||
|
||||
class AcceptHandlerTest extends APTestCase
|
||||
{
|
||||
public function testHandleInbox()
|
||||
{
|
||||
// TODO implement me
|
||||
$this->assertTrue( false );
|
||||
}
|
||||
|
||||
public function testHandleOutbox()
|
||||
{
|
||||
// TODO implement me
|
||||
$this->assertTrue( false );
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class CreateHandlerTest extends APTestCase
|
||||
{
|
||||
/**
|
||||
* @var EventDispatcher
|
||||
*/
|
||||
private $eventDispatcher;
|
||||
|
||||
public function setUp()
|
||||
|
@ -81,7 +81,7 @@ class FollowHandlerTest extends APTestCase
|
||||
'type' => 'Follow',
|
||||
'object' => 'https://example.com/actor/2',
|
||||
);
|
||||
$eventDispatcher->addListener( OutboxActivityEvent::NAME, function( $event )
|
||||
$eventDispatcher->addListener( OutboxActivityEvent::NAME, function()
|
||||
use ( &$outboxDispatched )
|
||||
{
|
||||
$outboxDispatched = true;
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test;
|
||||
|
||||
use ActivityPub\ActivityPub;
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\Auth;
|
||||
|
||||
use ActivityPub\Auth\AuthListener;
|
||||
|
@ -8,6 +8,9 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class AuthServiceTest extends APTestCase
|
||||
{
|
||||
/**
|
||||
* @var AuthService
|
||||
*/
|
||||
private $authService;
|
||||
|
||||
public function setUp()
|
||||
|
@ -4,8 +4,6 @@ namespace ActivityPub\Test\Auth;
|
||||
use DateTime;
|
||||
use ActivityPub\Auth\SignatureListener;
|
||||
use ActivityPub\Crypto\HttpSignatureService;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use ActivityPub\Test\TestUtils\TestDateTimeProvider;
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\Config;
|
||||
|
||||
use ActivityPub\Config\ActivityPubConfig;
|
||||
@ -9,6 +10,9 @@ use ActivityPub\Test\TestConfig\APTestCase;
|
||||
|
||||
class ActivityPubModuleTest extends APTestCase
|
||||
{
|
||||
/**
|
||||
* @var ActivityPubModule
|
||||
*/
|
||||
private $module;
|
||||
|
||||
public function setUp()
|
||||
|
@ -3,8 +3,6 @@ namespace ActivityPub\Test\Controllers;
|
||||
|
||||
use ActivityPub\Auth\AuthService;
|
||||
use ActivityPub\Controllers\GetController;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use ActivityPub\Objects\CollectionsService;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
|
@ -33,6 +33,9 @@ G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
|
||||
7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
|
||||
-----END RSA PRIVATE KEY-----";
|
||||
|
||||
/**
|
||||
* @var HttpSignatureService
|
||||
*/
|
||||
private $httpSignatureService;
|
||||
|
||||
public function setUp()
|
||||
|
@ -37,7 +37,7 @@ class RsaKeypairTest extends APTestCase
|
||||
$data = 'This is some data';
|
||||
$signature = 'not a real signature';
|
||||
$this->setExpectedException( \PHPUnit_Framework_Error::class );
|
||||
$verified = $keypair->verify( $data, $signature );
|
||||
$keypair->verify( $data, $signature );
|
||||
}
|
||||
|
||||
public function testItReturnsNotVerifiedForValidButWrongSignature()
|
||||
|
@ -1,8 +1,9 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\Entities;
|
||||
|
||||
use ActivityPub\Utils\DateTimeProvider;
|
||||
use DateTime;
|
||||
use ActivityPub\Crypto\RsaKeypair;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Database\PrefixNamingStrategy;
|
||||
use ActivityPub\Test\TestConfig\ArrayDataSet;
|
||||
@ -13,7 +14,13 @@ use Doctrine\ORM\Tools\Setup;
|
||||
|
||||
class EntityTest extends SQLiteTestCase
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
protected $entityManager;
|
||||
/**
|
||||
* @var DateTimeProvider
|
||||
*/
|
||||
protected $dateTimeProvider;
|
||||
|
||||
protected function getDataSet()
|
||||
@ -87,7 +94,7 @@ class EntityTest extends SQLiteTestCase
|
||||
$this->entityManager->flush();
|
||||
$newPrivateKey = 'a new private key';
|
||||
$object->setPrivateKey( $newPrivateKey );
|
||||
$this->entityManager->persiste( $object );
|
||||
$this->entityManager->persist( $object );
|
||||
$this->entityManager->flush();
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$expected = new ArrayDataSet( array(
|
||||
|
@ -2,7 +2,6 @@
|
||||
namespace ActivityPub\Test\Objects;
|
||||
|
||||
use ActivityPub\Utils\SimpleDateTimeProvider;
|
||||
use Exception;
|
||||
use ActivityPub\Auth\AuthService;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use ActivityPub\Objects\CollectionsService;
|
||||
|
@ -57,7 +57,6 @@ class IdProviderTest extends APTestCase
|
||||
);
|
||||
$idProvider = new IdProvider( $this->objectsService, $randomProvider, 'ap' );
|
||||
$request = Request::create( 'https://example.com' );
|
||||
$id = '';
|
||||
if ( array_key_exists( 'path', $testCase ) ) {
|
||||
$id = $idProvider->getId( $request, $testCase['path'] );
|
||||
} else {
|
||||
|
@ -1,16 +1,16 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\Objects;
|
||||
|
||||
use ActivityPub\Utils\DateTimeProvider;
|
||||
use DateTime;
|
||||
use BadMethodCallException;
|
||||
use ActivityPub\Test\TestConfig\SQLiteTestCase;
|
||||
use ActivityPub\Test\TestConfig\ArrayDataSet;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Database\PrefixNamingStrategy;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use ActivityPub\Test\TestUtils\TestDateTimeProvider;
|
||||
use Doctrine\ORM\Tools\Setup;
|
||||
use GuzzleHttp\Client;
|
||||
@ -18,9 +18,21 @@ use GuzzleHttp\Psr7\Response;
|
||||
|
||||
class ObjectsServiceTest extends SQLiteTestCase
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
protected $entityManager;
|
||||
/**
|
||||
* @var ObjectsService
|
||||
*/
|
||||
protected $objectsService;
|
||||
/**
|
||||
* @var DateTimeProvider
|
||||
*/
|
||||
protected $dateTimeProvider;
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
protected $httpClient;
|
||||
|
||||
protected function getDataSet()
|
||||
@ -67,7 +79,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'content' => 'This is a note',
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$expected = new ArrayDataSet( array(
|
||||
'objects' => array(
|
||||
array( 'id' => 1, 'created' => $now, 'lastUpdated' => $now )
|
||||
@ -166,7 +178,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
),
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$expected = new ArrayDataSet( array(
|
||||
'objects' => array(
|
||||
array( 'id' => 1, 'created' => $now, 'lastUpdated' => $now ),
|
||||
@ -267,7 +279,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
),
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$expected = new ArrayDataSet( array(
|
||||
'objects' => array(
|
||||
array( 'id' => 1, 'created' => $now, 'lastUpdated' => $now ),
|
||||
@ -366,7 +378,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
),
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$expected = new ArrayDataSet( array(
|
||||
'objects' => array(
|
||||
array( 'id' => 1, 'created' => $now, 'lastUpdated' => $now ),
|
||||
@ -535,7 +547,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'type' => 'Collection',
|
||||
'items' => array( "https://example.com/items/1" ),
|
||||
);
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$query = array(
|
||||
'id' => 'https://example.com/collections/1'
|
||||
);
|
||||
@ -782,7 +794,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'type' => 'Note',
|
||||
'content' => 'This is a note'
|
||||
);
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$found = $this->objectsService->dereference( 'https://example.com/note/2' );
|
||||
$this->assertNull( $found );
|
||||
}
|
||||
@ -795,7 +807,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'content' => 'This is a note'
|
||||
);
|
||||
$createTime = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$update = array( 'content' => 'This note has been updated' );
|
||||
$updateTime = $this->getTime( 'objects-service.update' );
|
||||
$this->objectsService->update( 'https://example.com/notes/1', $update );
|
||||
@ -860,7 +872,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
),
|
||||
);
|
||||
$createTime = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$update = array( 'attributedTo' => array(
|
||||
'id' => 'https://example.com/actors/2',
|
||||
) );
|
||||
@ -965,7 +977,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
),
|
||||
);
|
||||
$createTime = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$update = array( 'likes' => array(
|
||||
'https://example.com/likes/3',
|
||||
'https://example.com/likes/4',
|
||||
@ -1062,7 +1074,7 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'content' => 'This is a note'
|
||||
);
|
||||
$createTime = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->objectsService->persist( $fields );
|
||||
$update = array( 'content' => null );
|
||||
$updateTime = $this->getTime( 'objects-service.update' );
|
||||
$this->objectsService->update( 'https://example.com/notes/1', $update );
|
||||
@ -1114,7 +1126,6 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'type' => 'Note',
|
||||
'content' => 'This is a note',
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->assertEquals( $object['content'], 'This is a note' );
|
||||
$this->assertNull( $object['attributedTo'] );
|
||||
@ -1127,7 +1138,6 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'type' => 'Note',
|
||||
'content' => 'This is a note',
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->setExpectedException( BadMethodCallException::class );
|
||||
$object['content'] = 'This should break';
|
||||
@ -1140,7 +1150,6 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'type' => 'Note',
|
||||
'content' => 'This is a note',
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->setExpectedException( BadMethodCallException::class );
|
||||
unset( $object['content'] );
|
||||
@ -1156,7 +1165,6 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
'id' => 'https://example.com/actor/1'
|
||||
),
|
||||
);
|
||||
$now = $this->getTime( 'objects-service.create' );
|
||||
$object = $this->objectsService->persist( $fields );
|
||||
$this->assertEquals( $object['content'], 'This is a note' );
|
||||
$this->assertInstanceOf( ActivityPubObject::class, $object['attributedTo'] );
|
||||
@ -1271,9 +1279,10 @@ class ObjectsServiceTest extends SQLiteTestCase
|
||||
if ( array_key_exists( 'expectedQueryResults', $testCase ) ) {
|
||||
foreach ( $testCase['expectedQueryResults'] as $expectedQueryResult ) {
|
||||
$result = array_map(
|
||||
function( $obj ) { return $obj->asArray(); },
|
||||
function( ActivityPubObject $obj ) { return $obj->asArray(); },
|
||||
$this->objectsService->query( $expectedQueryResult['query'] )
|
||||
);
|
||||
$this->assertEquals( $expectedQueryResult['expectedResult'], $result );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\TestConfig;
|
||||
|
||||
use ActivityPub\ActivityPub;
|
||||
use ActivityPub\Config\ActivityPubConfig;
|
||||
use ActivityPub\Test\TestConfig\APTestCase;
|
||||
|
||||
abstract class SQLiteTestCase extends APTestCase
|
||||
{
|
||||
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\TestUtils;
|
||||
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Test\TestUtils\TestField;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test\TestUtils;
|
||||
|
||||
use DateTime;
|
||||
|
@ -3,7 +3,7 @@ namespace ActivityPub\Test\TestUtils;
|
||||
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Like a Field, but with fixed timestamps for testing
|
||||
@ -21,24 +21,24 @@ class TestField extends Field
|
||||
$this->fixedTime = $time;
|
||||
}
|
||||
|
||||
public function setTargetObject( ActivityPubObject $targetObject, $time = null )
|
||||
public function setTargetObject( ActivityPubObject $targetObject, DateTime $time = null )
|
||||
{
|
||||
parent::setTargetObject( $targetObject, $time );
|
||||
$this->lastUpdated = $this->fixedTime;
|
||||
}
|
||||
|
||||
public function setValue( $value, $time = null )
|
||||
public function setValue( $value, DateTime $time = null )
|
||||
{
|
||||
parent::setValue( $value, $time );
|
||||
$this->lastUpdated = $this->fixedTime;
|
||||
}
|
||||
|
||||
protected function setCreated( $timestamp )
|
||||
protected function setCreated( DateTime $timestamp )
|
||||
{
|
||||
// don't set created
|
||||
}
|
||||
|
||||
protected function setLastupdated( $timestamp )
|
||||
protected function setLastupdated( DateTime $timestamp )
|
||||
{
|
||||
// don't set lastUpdated
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
<?php
|
||||
<?php /** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
namespace ActivityPub\Test;
|
||||
|
||||
use ActivityPub\ActivityPub;
|
||||
|
Loading…
Reference in New Issue
Block a user