[WIP] Begin writing PostController test; refactor testing APObjects
This commit is contained in:
parent
94777ef55a
commit
ffca344f03
@ -28,7 +28,7 @@ class ActivityEvent extends Event
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
protected function __construct( array $activity, ActivityPubObject $actor,
|
||||
public function __construct( array $activity, ActivityPubObject $actor,
|
||||
Request $request )
|
||||
{
|
||||
$this->activity = $activity;
|
||||
|
@ -43,12 +43,13 @@ class PostController
|
||||
public function handle( Request $request )
|
||||
{
|
||||
$uri = $this->getUriWithoutQuery( $request );
|
||||
$object = $this->objectsService->dereference( $uri );
|
||||
$object = $this->objectsService->query( array( 'id' => $uri ) );
|
||||
if ( ! $object ) {
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
$actorWithInbox = $this->objectWithField( 'inbox', $uri );
|
||||
if ( $actorWithInbox ) {
|
||||
$inboxField = $object->getReferencingField( 'inbox' );
|
||||
if ( $inboxField ) {
|
||||
$actorWithInbox = $inboxField->getObject();
|
||||
if ( ! $request->attributes->has( 'signed' ) ||
|
||||
! $this->authorized( $request, $actorWithInbox ) ) {
|
||||
throw new UnauthorizedHttpException();
|
||||
@ -61,8 +62,9 @@ class PostController
|
||||
$this->eventDispatcher->dispatch( InboxActivityEvent::NAME, $event );
|
||||
return;
|
||||
}
|
||||
$actorWithOutbox = $this->objectWithField( 'outbox', $uri );
|
||||
if ( $actorWithOutbox ) {
|
||||
$outboxField = $object->getReferencingField( 'outbox' );
|
||||
if ( $outboxField ) {
|
||||
$actorWithOutbox = $outboxField->getObject();
|
||||
if ( ! $this->authorized( $request, $actorWithOutbox ) ) {
|
||||
throw new UnauthorizedHttpException();
|
||||
}
|
||||
|
@ -201,6 +201,36 @@ class ActivityPubObject implements ArrayAccess
|
||||
$this->lastUpdated = $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the object is referenced by a field with key $name
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasReferencingField( string $name )
|
||||
{
|
||||
foreach( $this->getReferencingFields() as $field ) {
|
||||
if ( $field->getName() === $name ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the referencing field named $field, if it exists
|
||||
*
|
||||
* @param string $name The name of the referencing to get
|
||||
* @return Field|null
|
||||
*/
|
||||
public function getReferencingField( string $name )
|
||||
{
|
||||
foreach( $this->getReferencingFields() as $field ) {
|
||||
if ( $field->getName() === $name ) {
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new field that references this object
|
||||
*
|
||||
|
@ -67,6 +67,15 @@ class Field
|
||||
*/
|
||||
protected $lastUpdated;
|
||||
|
||||
protected function __construct( DateTime $time = null )
|
||||
{
|
||||
if ( ! $time ) {
|
||||
$time = new DateTime( "now" );
|
||||
}
|
||||
$this->created = $time;
|
||||
$this->lastUpdated = $time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new field with a string value
|
||||
*
|
||||
@ -80,12 +89,10 @@ class Field
|
||||
if ( ! $time ) {
|
||||
$time = new DateTime( "now" );
|
||||
}
|
||||
$field = new Field();
|
||||
$field = new Field( $time );
|
||||
$field->setObject( $object, $time );
|
||||
$field->setName( $name );
|
||||
$field->setValue( $value );
|
||||
$field->setCreated( $time );
|
||||
$field->setLastUpdated( $time );
|
||||
$field->setValue( $value, $time );
|
||||
return $field;
|
||||
}
|
||||
|
||||
@ -97,17 +104,18 @@ class Field
|
||||
* @param ActivityPubObject $targetObject The object that this field holds
|
||||
* @return Field The new field
|
||||
*/
|
||||
public static function withObject( ActivityPubObject $object, string $name, Object $targetObject, DateTime $time = null )
|
||||
public static function withObject( ActivityPubObject $object,
|
||||
string $name,
|
||||
ActivityPubObject $targetObject,
|
||||
DateTime $time = null )
|
||||
{
|
||||
if ( ! $time ) {
|
||||
$time = new DateTime( "now" );
|
||||
}
|
||||
$field = new Field();
|
||||
$field = new Field( $time );
|
||||
$field->setObject( $object, $time );
|
||||
$field->setName( $name );
|
||||
$field->setTargetObject( $targetObject );
|
||||
$field->setCreated( $time );
|
||||
$field->setLastUpdated( $time );
|
||||
$field->setTargetObject( $targetObject, $time );
|
||||
return $field;
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ namespace ActivityPub\Test\Auth;
|
||||
use ActivityPub\Auth\AuthListener;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Test\TestUtils\TestUtils;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
@ -18,10 +18,10 @@ class AuthListenerTest extends TestCase
|
||||
{
|
||||
$this->objectsService = $this->createMock( ObjectsService::class );
|
||||
$this->objectsService->method( 'dereference' )->will( $this->returnValueMap( array(
|
||||
array( 'https://example.com/actor/1', TestUtils::objectFromArray( array(
|
||||
array( 'https://example.com/actor/1', TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/1',
|
||||
) ) ),
|
||||
array( 'https://example.com/actor/2', TestUtils::objectFromArray( array(
|
||||
array( 'https://example.com/actor/2', TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/2',
|
||||
) ) ),
|
||||
) ) );
|
||||
@ -45,7 +45,7 @@ class AuthListenerTest extends TestCase
|
||||
return 'https://example.com/actor/1';
|
||||
},
|
||||
'expectedAttributes' => array(
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/1',
|
||||
) ),
|
||||
),
|
||||
@ -56,12 +56,12 @@ class AuthListenerTest extends TestCase
|
||||
return 'https://example.com/actor/1';
|
||||
},
|
||||
'requestAttributes' => array(
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/2',
|
||||
) ),
|
||||
),
|
||||
'expectedAttributes' => array(
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/2',
|
||||
) ),
|
||||
),
|
||||
|
@ -2,7 +2,7 @@
|
||||
namespace ActivityPub\Test\Auth;
|
||||
|
||||
use ActivityPub\Auth\AuthService;
|
||||
use ActivityPub\Test\TestUtils\TestUtils;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
@ -64,7 +64,7 @@ class AuthServiceTest extends TestCase
|
||||
if ( array_key_exists( 'actor', $testCase ) ) {
|
||||
$request->attributes->set( 'actor', $testCase['actor'] );
|
||||
}
|
||||
$object = TestUtils::objectFromArray( $testCase['object'] );
|
||||
$object = TestActivityPubObject::fromArray( $testCase['object'] );
|
||||
$actual = $this->authService->isAuthorized( $request, $object );
|
||||
$this->assertEquals(
|
||||
$testCase['expectedResult'], $actual, "Error on test $testCase[id]"
|
||||
|
@ -7,8 +7,8 @@ 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;
|
||||
use ActivityPub\Test\TestUtils\TestUtils;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
@ -44,8 +44,8 @@ oYi+1hqp1fIekaxsyQIDAQAB
|
||||
$objectsService = $this->createMock( ObjectsService::class );
|
||||
$objectsService->method( 'dereference' )
|
||||
->will( $this->returnValueMap( array(
|
||||
array( self::KEY_ID, TestUtils::objectFromArray( self::KEY ) ),
|
||||
array( self::ACTOR_ID, TestUtils::objectFromArray( self::ACTOR ) ),
|
||||
array( self::KEY_ID, TestActivityPubObject::fromArray( self::KEY ) ),
|
||||
array( self::ACTOR_ID, TestActivityPubObject::fromArray( self::ACTOR ) ),
|
||||
) ) );
|
||||
$this->signatureListener = new SignatureListener(
|
||||
$httpSignatureService, $objectsService
|
||||
@ -85,7 +85,7 @@ oYi+1hqp1fIekaxsyQIDAQAB
|
||||
),
|
||||
'expectedAttributes' => array(
|
||||
'signed' => true,
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/1',
|
||||
) ),
|
||||
),
|
||||
@ -96,13 +96,13 @@ oYi+1hqp1fIekaxsyQIDAQAB
|
||||
'Authorization' => 'Signature keyId="https://example.com/actor/1/key",algorithm="rsa-sha256",headers="(request-target) host date", signature="qdx+H7PHHDZgy4y/Ahn9Tny9V3GP6YgBPyUXMmoxWtLbHpUnXS2mg2+SbrQDMCJypxBLSPQR2aAjn7ndmw2iicw3HMbe8VfEdKFYRqzic+efkb3nndiv/x1xSHDJWeSWkx3ButlYSuBskLu6kd9Fswtemr3lgdDEmn04swr2Os0="',
|
||||
),
|
||||
'requestAttributes' => array(
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/2',
|
||||
) ),
|
||||
),
|
||||
'expectedAttributes' => array(
|
||||
'signed' => true,
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/2',
|
||||
) ),
|
||||
),
|
||||
@ -114,7 +114,7 @@ oYi+1hqp1fIekaxsyQIDAQAB
|
||||
),
|
||||
'expectedAttributes' => array(
|
||||
'signed' => true,
|
||||
'actor' => TestUtils::objectFromArray( array(
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/1',
|
||||
) ),
|
||||
),
|
||||
@ -137,27 +137,11 @@ oYi+1hqp1fIekaxsyQIDAQAB
|
||||
}
|
||||
}
|
||||
$this->signatureListener->validateHttpSignature( $event );
|
||||
foreach ( $testCase['expectedAttributes'] as $expectedKey => $expectedValue ) {
|
||||
$this->assertTrue(
|
||||
$event->getRequest()->attributes->has( $expectedKey ),
|
||||
"Error on test $testCase[id]"
|
||||
);
|
||||
xdebug_break();
|
||||
if ( $expectedValue instanceof ActivityPubObject ) {
|
||||
$this->assertTrue(
|
||||
$expectedValue->equals(
|
||||
$event->getRequest()->attributes->get( $expectedKey )
|
||||
),
|
||||
"Error on test $testCase[id]"
|
||||
);
|
||||
} else {
|
||||
$this->assertEquals(
|
||||
$expectedValue,
|
||||
$event->getRequest()->attributes->get( $expectedKey ),
|
||||
"Error on test $testCase[id]"
|
||||
);
|
||||
}
|
||||
}
|
||||
$this->assertEquals(
|
||||
$testCase['expectedAttributes'],
|
||||
$event->getRequest()->attributes->all(),
|
||||
"Error on test $testCase[id]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use ActivityPub\Objects\CollectionsService;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Test\TestUtils\TestUtils;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@ -59,7 +59,7 @@ class GetControllerTest extends TestCase
|
||||
$objectsService->method( 'dereference' )->will(
|
||||
$this->returnCallback( function( $uri ) {
|
||||
if ( array_key_exists( $uri, self::OBJECTS ) ) {
|
||||
return TestUtils::objectFromArray( self::OBJECTS[$uri] );
|
||||
return TestActivityPubObject::fromArray( self::OBJECTS[$uri] );
|
||||
}
|
||||
})
|
||||
);
|
||||
|
@ -1,14 +1,96 @@
|
||||
<?php
|
||||
namespace ActivityPub\Test\Controllers;
|
||||
|
||||
use ActivityPub\Activities\InboxActivityEvent;
|
||||
use ActivityPub\Activities\OutboxActivityEvent;
|
||||
use ActivityPub\Controllers\PostController;
|
||||
use ActivityPub\Objects\ObjectsService;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class PostControllerTest extends TestCase
|
||||
{
|
||||
public function testOutboxController()
|
||||
const OBJECTS = array(
|
||||
'https://example.com/actor/1/inbox' => array(
|
||||
'id' => 'https://example.com/actor/1/inbox',
|
||||
),
|
||||
);
|
||||
|
||||
public function testPostController()
|
||||
{
|
||||
// TODO implement me
|
||||
$this->assertTrue( false );
|
||||
$objectsService = $this->createMock( ObjectsService::class );
|
||||
$objectsService->method( 'query' )->will(
|
||||
$this->returnCallback( function( $query ) {
|
||||
if ( array_key_exists( 'id', $query ) &&
|
||||
array_key_exists( $query['id'], self::OBJECTS ) ) {
|
||||
return array( TestActivityPubObject::fromArray(
|
||||
self::OBJECTS[$query['id']]
|
||||
) );
|
||||
} else {
|
||||
return array();
|
||||
}
|
||||
} )
|
||||
);
|
||||
$testCases = array(
|
||||
array(
|
||||
'id' => 'basicInboxTest',
|
||||
'request' => Request::create(
|
||||
'https://example.com/actor/1/inbox',
|
||||
Request::METHOD_POST,
|
||||
array(), array(), array(), array(),
|
||||
'{"type": "Create"}'
|
||||
),
|
||||
'requestAttributes' => array(
|
||||
'signed' => true,
|
||||
'actor' => TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/1',
|
||||
'inbox' => array(
|
||||
'id' => 'https://example.com/actor/1/inbox',
|
||||
)
|
||||
) ),
|
||||
),
|
||||
'expectedEventName' => InboxActivityEvent::NAME,
|
||||
'expectedEvent' => new InboxActivityEvent(
|
||||
array( 'type' => 'Create' ),
|
||||
TestActivityPubObject::fromArray( array(
|
||||
'id' => 'https://example.com/actor/1',
|
||||
'inbox' => array(
|
||||
'id' => 'https://example.com/actor/1/inbox',
|
||||
)
|
||||
) ),
|
||||
Request::create(
|
||||
'https://example.com/actor/1/inbox',
|
||||
Request::METHOD_POST,
|
||||
array(), array(), array(), array(),
|
||||
'{"type": "Create"}'
|
||||
)
|
||||
),
|
||||
),
|
||||
);
|
||||
foreach ( $testCases as $testCase ) {
|
||||
$eventDispatcher = $this->getMockBuilder( EventDispatcher::class )
|
||||
->setMethods( array( 'dispatch' ) )
|
||||
->getMock();
|
||||
if ( array_key_exists( 'expectedEvent', $testCase ) ) {
|
||||
$eventDispatcher->expects( $this->once() )
|
||||
->method( 'dispatch' )
|
||||
->with(
|
||||
$this->equalTo($testCase['expectedEventName']),
|
||||
$this->equalTo($testCase['expectedEvent'])
|
||||
);
|
||||
}
|
||||
$postController = new PostController( $eventDispatcher, $objectsService );
|
||||
$request = $testCase['request'];
|
||||
if ( array_key_exists( 'requestAttributes', $testCase ) ) {
|
||||
$request->attributes->add( $testCase['requestAttributes'] );
|
||||
}
|
||||
if ( array_key_exists( 'expectedException', $testCase ) ) {
|
||||
$this->expectException( $testCase['expectedException'] );
|
||||
}
|
||||
$postController->handle( $request );
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -5,7 +5,7 @@ use Exception;
|
||||
use ActivityPub\Auth\AuthService;
|
||||
use ActivityPub\Objects\ContextProvider;
|
||||
use ActivityPub\Objects\CollectionsService;
|
||||
use ActivityPub\Test\TestUtils\TestUtils;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@ -370,7 +370,8 @@ class CollectionsServiceTest extends TestCase
|
||||
$request->attributes->add( $testCase['requestAttributes'] );
|
||||
}
|
||||
$actual = $this->collectionsService->pageAndFilterCollection(
|
||||
$testCase['request'], TestUtils::objectFromArray( $testCase['collection'] )
|
||||
$testCase['request'],
|
||||
TestActivityPubObject::fromArray( $testCase['collection'] )
|
||||
);
|
||||
$this->assertEquals(
|
||||
$testCase['expectedResult'], $actual, "Error on test $testCase[id]"
|
||||
|
65
test/TestUtils/TestActivityPubObject.php
Normal file
65
test/TestUtils/TestActivityPubObject.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
namespace ActivityPub\Test\TestUtils;
|
||||
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Test\TestUtils\TestField;
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Like an ActivityPubObject, but with fixed timestamps for testing
|
||||
*/
|
||||
class TestActivityPubObject extends ActivityPubObject
|
||||
{
|
||||
public static function getDefaultTime() {
|
||||
return DateTime::createFromFormat(
|
||||
DateTime::RFC2822, 'Sun, 05 Jan 2014 21:31:40 GMT'
|
||||
);
|
||||
}
|
||||
|
||||
private $fixedTime;
|
||||
|
||||
public function __construct( DateTime $time = null )
|
||||
{
|
||||
if ( ! $time ) {
|
||||
$time = self::getDefaultTime();
|
||||
}
|
||||
$this->fixedTime = $time;
|
||||
parent::__construct( $time );
|
||||
}
|
||||
|
||||
public function addField( Field $field, DateTime $time = null )
|
||||
{
|
||||
parent::addField( $field, $time );
|
||||
$this->lastUpdated = $this->fixedTime;
|
||||
}
|
||||
|
||||
public function removeField( Field $field, DateTime $time = null )
|
||||
{
|
||||
parent::removeField( $field, $time );
|
||||
$this->lastUpdated = $this->fixedTime;
|
||||
}
|
||||
|
||||
public function setLastUpdated( $lastUpdated )
|
||||
{
|
||||
// do not change lastUpdated
|
||||
}
|
||||
|
||||
public static function fromArray( array $arr, DateTime $time = null )
|
||||
{
|
||||
if ( ! $time ) {
|
||||
$time = self::getDefaultTime();
|
||||
}
|
||||
$object = new TestActivityPubObject( $time );
|
||||
foreach ( $arr as $name => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$child = self::fromArray( $value, $time );
|
||||
TestField::withObject( $object, $name, $child, $time );
|
||||
} else {
|
||||
TestField::withValue( $object, $name, $value, $time );
|
||||
}
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
?>
|
46
test/TestUtils/TestField.php
Normal file
46
test/TestUtils/TestField.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace ActivityPub\Test\TestUtils;
|
||||
|
||||
use ActivityPub\Entities\Field;
|
||||
use ActivityPub\Test\TestUtils\TestActivityPubObject;
|
||||
|
||||
/**
|
||||
* Like a Field, but with fixed timestamps for testing
|
||||
*/
|
||||
class TestField extends Field
|
||||
{
|
||||
private $fixedTime;
|
||||
|
||||
protected function __construct( $time = null )
|
||||
{
|
||||
if ( ! $time ) {
|
||||
$time = TestActivityPubObject::getDefaultTime();
|
||||
}
|
||||
parent::__construct( $time );
|
||||
$this->fixedTime = $time;
|
||||
}
|
||||
|
||||
public function setTargetObject( $targetObject, $time = null )
|
||||
{
|
||||
parent::setTargetObject( $targetObject, $time );
|
||||
$this->lastUpdated = $this->fixedTime;
|
||||
}
|
||||
|
||||
public function setValue( $value, $time = null )
|
||||
{
|
||||
parent::setValue( $value, $time );
|
||||
$this->lastUpdated = $this->fixedTime;
|
||||
}
|
||||
|
||||
protected function setCreated( $timestamp )
|
||||
{
|
||||
// don't set created
|
||||
}
|
||||
|
||||
protected function setLastupdated( $timestamp )
|
||||
{
|
||||
// don't set lastUpdated
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
namespace ActivityPub\Test\TestUtils;
|
||||
|
||||
use ActivityPub\Entities\ActivityPubObject;
|
||||
use ActivityPub\Entities\Field;
|
||||
|
||||
class TestUtils
|
||||
{
|
||||
public static function objectFromArray( $array ) {
|
||||
$object = new ActivityPubObject();
|
||||
foreach ( $array as $name => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$child = self::objectFromArray( $value );
|
||||
Field::withObject( $object, $name, $child );
|
||||
} else {
|
||||
Field::withValue( $object, $name, $value );
|
||||
}
|
||||
}
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
?>
|
Loading…
Reference in New Issue
Block a user