diff --git a/plugins/ActivityPub/ActivityPub.php b/plugins/ActivityPub/ActivityPub.php new file mode 100644 index 0000000000..23559e1a41 --- /dev/null +++ b/plugins/ActivityPub/ActivityPub.php @@ -0,0 +1,79 @@ +connect( + 'activitypub_inbox', + '{gsactor_id<\d+>}/inbox', + [Inbox::class, 'handle'], + options: ['accept' => self::$accept_headers] + ); + return Event::next; + } + + /** + * Validate HTTP Accept headers + * + * @param null|array|string $accept + * @param bool $strict Strict mode + * + * @throws \Exception when strict mode enabled + * + * @return bool + */ + public static function validateAcceptHeader(array|string|null $accept, bool $strict): bool + { + if (is_string($accept) + && in_array($accept, self::$accept_headers) + ) { + return true; + } elseif (is_array($accept) + && count( + array_intersect($accept, self::$accept_headers) + ) + ) { + return true; + } + + if (!$strict) { + return false; + } + + throw new Exception( + sprintf( + "HTTP Accept header error. Given: '%s'", + $accept + ) + ); + } +} \ No newline at end of file diff --git a/plugins/ActivityPub/Controller/Inbox.php b/plugins/ActivityPub/Controller/Inbox.php new file mode 100644 index 0000000000..17e783cf30 --- /dev/null +++ b/plugins/ActivityPub/Controller/Inbox.php @@ -0,0 +1,71 @@ +. + +// }}} + +namespace Plugin\ActivityPub\Controller; + +use App\Core\Controller; +use App\Core\DB\DB; +use function App\Core\I18n\_m; +use App\Util\Exception\ClientException; +use Plugin\ActivityPub\ActivityPub; +use Plugin\ActivityStreamsTwo\Util\Model\AS2ToEntity\AS2ToEntity; +use Plugin\ActivityStreamsTwo\Util\Response\TypeResponse; +use Plugin\ActivityStreamsTwo\Util\Type; +use Plugin\ActivityStreamsTwo\Util\Type\Util; + +class Inbox extends Controller +{ + /** + * Inbox handler + */ + public function handle(int $gsactor_id) + { + $user = DB::find('local_user', ['id' => $gsactor_id]); + if (is_null($user)) { + throw new ClientException(_m('No such actor.'), 404); + } + + // Check accept header + ActivityPub::validateAcceptHeader( + $this->request->headers->get('accept'), + true + ); + + // Check current actor can post + + // Get content + $payload = Util::decodeJson( + (string) $this->request->getContent() + ); + + // Cast as an ActivityStreams type + $type = Type::create($payload); + + dd(AS2ToEntity::translate($type->toArray()['object'])); + + // $http_signature = new HttpSignature($this->server); + // if ($http_signature->verify($request)) { + // return new Response('', 201); + // } + + return new TypeResponse($type, status: 202); + } +} diff --git a/plugins/ActivityStreamsTwo/ActivityStreamsTwo.php b/plugins/ActivityStreamsTwo/ActivityStreamsTwo.php new file mode 100644 index 0000000000..c409d4e8d0 --- /dev/null +++ b/plugins/ActivityStreamsTwo/ActivityStreamsTwo.php @@ -0,0 +1,67 @@ +accept, $accept))) { + return Event::next; + } + switch ($route) { + case 'note_show': + $response = NoteResponse::handle($vars['note']); + return Event::stop; + default: + return Event::next; + } + } + + /** + * This code executes when GNU social creates the page routing, and we hook + * on this event to add our action handler for Embed. + * + * @param $r RouteLoader the router that was initialized. + * + * @return bool + * + * public function onAddRoute(RouteLoader $r): bool + * { + * $r->connect( + * 'note_view', + * '/note/{id<\d+>}', + * [NoteResponse::class, 'handle'], + * options: ['accept' => $this->accept] + * ); + * return Event::next; + * }*/ +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/README.md b/plugins/ActivityStreamsTwo/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/plugins/ActivityStreamsTwo/Util/Model/AS2ToEntity/AS2ToEntity.php b/plugins/ActivityStreamsTwo/Util/Model/AS2ToEntity/AS2ToEntity.php new file mode 100644 index 0000000000..bc9f47f011 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Model/AS2ToEntity/AS2ToEntity.php @@ -0,0 +1,21 @@ + AS2ToNote::translate($activity), + default => Entity::create($activity), + }; + } +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/Util/Model/AS2ToEntity/AS2ToNote.php b/plugins/ActivityStreamsTwo/Util/Model/AS2ToEntity/AS2ToNote.php new file mode 100644 index 0000000000..4a06fc96a9 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Model/AS2ToEntity/AS2ToNote.php @@ -0,0 +1,37 @@ + false, + 'created' => new DateTime($args['published'] ?? 'now'), + 'rendered' => $args['content'] ?? null, + 'modified' => new DateTime(), + ]; + if (!is_null($map['rendered'])) { + $map['content'] = Security::sanitize($map['rendered']); + } + + $obj = new Note(); + foreach ($map as $prop => $val) { + $set = "set{$prop}"; + $obj->{$set}($val); + } + return $obj; + } +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/Util/Model/EntityToType/EntityToType.php b/plugins/ActivityStreamsTwo/Util/Model/EntityToType/EntityToType.php new file mode 100644 index 0000000000..16eba06831 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Model/EntityToType/EntityToType.php @@ -0,0 +1,28 @@ + 'Object', + ]; + return Type::create($map); + } + } +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/Util/Model/EntityToType/NoteToType.php b/plugins/ActivityStreamsTwo/Util/Model/EntityToType/NoteToType.php new file mode 100644 index 0000000000..2761ee59c3 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Model/EntityToType/NoteToType.php @@ -0,0 +1,33 @@ + 'https://www.w3.org/ns/activitystreams', + 'id' => Router::url('note_view', ['id' => $note->getId()], Router::ABSOLUTE_URL), + 'published' => $note->getCreated()->format(DateTimeInterface::RFC3339), + //'attributedTo' => Router::url('actor', ['id' => $note->getGSActorId()]), + //'to' => $to, + //'cc' => $cc, + 'content' => json_encode($note->getContent()), // change to rendered + //'tag' => $tags + ]; + return Type::create(type: 'Note', attributes: $attr); + } +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/Util/Response/AbstractResponse.php b/plugins/ActivityStreamsTwo/Util/Response/AbstractResponse.php new file mode 100644 index 0000000000..2b874da483 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Response/AbstractResponse.php @@ -0,0 +1,24 @@ + $id]); + return new TypeResponse(data: NoteToType::translate($note), status: $status); + } +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/Util/Response/TypeResponse.php b/plugins/ActivityStreamsTwo/Util/Response/TypeResponse.php new file mode 100644 index 0000000000..a33a296454 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Response/TypeResponse.php @@ -0,0 +1,24 @@ +toJson() : null, + status: $status, + headers: ['content-type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'], + json: true + ); + } +} \ No newline at end of file diff --git a/plugins/ActivityStreamsTwo/Util/Type.php b/plugins/ActivityStreamsTwo/Util/Type.php new file mode 100644 index 0000000000..4dd1b5ebed --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type.php @@ -0,0 +1,125 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\AbstractObject; +use Plugin\ActivityStreamsTwo\Util\Type\TypeResolver; +use Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \ActivityPhp\Type is a Factory for ActivityStreams 2.0 types. + * + * It provides shortcuts methods for type instantiation and more. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#types + * @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types + * @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types + * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types + */ +abstract class Type +{ + /** + * Factory method to create type instance and set attributes values + * + * To see which default types are defined and their attributes: + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#types + * @see https://www.w3.org/TR/activitystreams-vocabulary/#activity-types + * @see https://www.w3.org/TR/activitystreams-vocabulary/#actor-types + * @see https://www.w3.org/TR/activitystreams-vocabulary/#object-types + * + * @param array|string $type + * @param array $attributes + * + * @throws Exception + * + * @return mixed + */ + public static function create($type, array $attributes = []) + { + if (!is_string($type) && !is_array($type)) { + throw new Exception( + 'Type parameter must be a string or an array. Given=' + . gettype($type) + ); + } + + if (is_array($type)) { + if (!isset($type['type'])) { + throw new Exception( + "Type parameter must have a 'type' key" + ); + } + + $attributes = $type; + } + + try { + $class = is_array($type) + ? TypeResolver::getClass($type['type']) + : TypeResolver::getClass($type); + } catch (Exception $exception) { + $message = json_encode($attributes, JSON_PRETTY_PRINT); + throw new Exception( + $exception->getMessage() . "\n{$message}" + ); + } + + if (is_string($class)) { + $class = new $class(); + } + + foreach ($attributes as $name => $value) { + try { + $class->set($name, $value); + } catch (Exception) { + // Discard invalid properties + } + } + + return $class; + } + + /** + * Create an activitystream type from a JSON string + */ + public static function fromJson(string $json): AbstractObject + { + $data = json_decode($json, true); + + if (json_last_error() === JSON_ERROR_NONE + && is_array($data) + ) { + return self::create($data); + } + + throw new Exception( + sprintf( + "An error occurred during the JSON decoding.\n '%s'", + $json + ) + ); + } + + /** + * Add a custom validator for an attribute. + * It checks that it implements Validator\Interface + * + * @param string $name An attribute name to validate. + * @param string $class A validator class name + */ + public static function addValidator(string $name, string $class): void + { + Validator::add($name, $class); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/AbstractObject.php b/plugins/ActivityStreamsTwo/Util/Type/AbstractObject.php new file mode 100644 index 0000000000..c2cca91b87 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/AbstractObject.php @@ -0,0 +1,398 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type; + +use function array_key_exists; +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type; +use ReflectionClass; + +/** + * \ActivityPhp\Type\ObjectAbstract is an abstract class for all + * Activity Streams Core Types. + * + * @see https://www.w3.org/TR/activitystreams-core/#model + */ +abstract class AbstractObject +{ + /** + * Keep all properties values that have been set + * + * @var array + */ + private array $_props = []; + + /** + * Standard setter method + * - Perform content validation if a validator exists + * + * @param string $name + * @param mixed $value + * + * @throws Exception + * + * @return $this + */ + public function set(string $name, mixed $value): static + { + // Throws an exception when property is undefined + if ($name !== '@context') { + $this->has($name); + } + + // Validate given value + if (!Validator::validate($name, $value, $this)) { + $message = "Rejected value. Type='%s', Property='%s', value='%s'"; + throw new Exception( + sprintf( + $message, + static::class, + $name, + print_r($value, true) + ) + . PHP_EOL + ); + } + + // @context has a special role + if ($name === '@context') { + $this->_props[$name] = $value; + + // All modes and property defined + } elseif ($this->has($name)) { + $this->_props[$name] = $this->transform($value); + + // Undefined property but it's valid as it was + // tested in the if clause above (no exception) so, let's include it + } else { + $this->_props[$name] = $this->transform($value); + } + + return $this; + } + + /** + * Affect a value to a property or an extended property + * + * @param mixed $value + * + * @throws Exception + * + * @return mixed + */ + private function transform(mixed $value): mixed + { + // Deep typing + if (is_array($value)) { + if (isset($value['type'])) { + return Type::create($value); + } elseif (is_int(key($value))) { + return array_map( + static function ($value) { + return is_array($value) && isset($value['type']) + ? Type::create($value) + : $value; + }, + $value + ); + // Empty array, array that should not be cast as ActivityStreams types + } else { + return $value; + } + } else { + // Scalars + return $value; + } + } + + /** + * Standard getter method + * + * @param string $name + * + * @throws Exception + * + * @return mixed + */ + public function get(string $name): mixed + { + // Throws an exception when property is undefined + $this->has($name); + + return $this->_props[$name]; + } + + /** + * Checks that property exists + * + * @param string $name + * @param bool $strict + * + * @throws Exception + * + * @return bool + */ + public function has(string $name): bool + { + if (isset($this->{$name})) { + if (!array_key_exists($name, $this->_props)) { + $this->_props[$name] = $this->{$name}; + } + + return true; + } + + if (array_key_exists($name, $this->_props)) { + return true; + } + + $reflect = new ReflectionClass(Type::create($this->type)); + $allowed_props = $reflect->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED); + $allowed = []; + foreach ($allowed_props as $prop) { + $allowed[] = $prop->getName(); + } + if (!in_array($name, $allowed)) { + sort($allowed); + throw new Exception( + sprintf( + 'Property "%s" is not defined. Type="%s", ' . + 'Class="%s"' . PHP_EOL . 'Allowed properties: %s', + $name, + $this->get('type'), + static::class, + implode(', ', $allowed) + ) + ); + } else { + return false; + } + } + + /** + * Get a list of all properties names + * + * @return array + */ + public function getProperties(): array + { + return array_values( + array_unique( + array_merge( + array_keys($this->_props), + array_keys( + array_diff_key( + get_object_vars($this), + ['_props' => '1'] + ) + ) + ) + ) + ); + } + + /** + * Get a list of all properties and their values + * as an associative array. + * Null values are not returned. + */ + public function toArray(): array + { + $keys = array_keys( + array_filter( + get_object_vars($this), + static function ($value, $key): bool { + return !is_null($value) && $key !== '_props'; + }, + ARRAY_FILTER_USE_BOTH + ) + ); + + $stack = []; + + // native properties + foreach ($keys as $key) { + if ($this->{$key} instanceof self) { + $stack[$key] = $this->{$key}->toArray(); + } elseif (!is_array($this->{$key})) { + $stack[$key] = $this->{$key}; + } elseif (is_array($this->{$key})) { + if (is_int(key($this->{$key}))) { + $stack[$key] = array_map( + static function ($value) { + return $value instanceof self + ? $value->toArray() + : $value; + }, + $this->{$key} + ); + } else { + $stack[$key] = $this->{$key}; + } + } + } + + // _props + foreach ($this->_props as $key => $value) { + if (is_null($value)) { + continue; + } + + if ($value instanceof self) { + $stack[$key] = $value->toArray(); + } elseif (!is_array($value)) { + $stack[$key] = $value; + } else { + if (is_int(key($value))) { + $stack[$key] = array_map( + static function ($value) { + return $value instanceof self + ? $value->toArray() + : $value; + }, + $value + ); + } else { + $stack[$key] = $value; + } + } + } + + return $stack; + } + + /** + * Get a JSON + * + * @param null|int $options PHP JSON options + * + * @return string + */ + public function toJson(?int $options = null): string + { + return json_encode( + $this->toArray(), + (int) $options + ); + } + + /** + * Get a copy of current object and return a new instance + * + * @throws Exception + * + * @return self A new instance of this object + */ + public function copy(): self + { + return Type::create( + $this->type, + $this->toArray() + ); + } + + /** + * Extend current type properties + * + * @param string $property + * @param mixed $default + * + * @throws Exception + */ + public function extend(string $property, mixed $default = null): void + { + if ($this->has($property)) { + return; + } + + if (!array_key_exists($property, $this->_props)) { + $this->_props[$property] = $default; + } + } + + /** + * Magical isset method + */ + public function __isset(string $name): bool + { + return property_exists($this, $name) + || array_key_exists($name, $this->_props); + } + + /** + * Magical setter method + * + * @param string $name + * @param mixed $value + * + * @throws Exception + */ + public function __set(string $name, mixed $value): void + { + $this->set($name, $value); + } + + /** + * Magical getter method + * + * @param string $name + * + * @throws Exception + * + * @return mixed + */ + public function __get(string $name): mixed + { + return $this->get($name); + } + + /** + * Overloading methods + * + * @param string $name + * @param null|array $arguments + * + * @throws Exception + * + * @return mixed + */ + public function __call(string $name, ?array $arguments = []) + { + // Getters + if (str_starts_with($name, 'get')) { + $attr = lcfirst(substr($name, 3)); + return $this->get($attr); + } + + // Setters + if (str_starts_with($name, 'set')) { + if (count($arguments) === 1) { + $attr = lcfirst(substr($name, 3)); + return $this->set($attr, $arguments[0]); + } else { + throw new Exception( + sprintf( + 'Expected exactly one argument for method "%s()"', + $name + ) + ); + } + } + + throw new Exception( + sprintf( + 'Method "%s" is not defined', + $name + ) + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/AbstractActivity.php b/plugins/ActivityStreamsTwo/Util/Type/Core/AbstractActivity.php new file mode 100644 index 0000000000..038067ced1 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/AbstractActivity.php @@ -0,0 +1,111 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\AbstractActivity implements only common + * attributes between Activity and IntransitiveActivity. + * + * It SHOULD NOT be used as if. + * + * Please use IntransitiveActivity or Activity instead. + * + * @see https://www.w3.org/TR/activitystreams-core/#activities + * @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities + */ +abstract class AbstractActivity extends ObjectType +{ + /** + * @var string + */ + protected string $id; + + /** + * Describes one or more entities that either performed or are + * expected to perform the activity. + * Any single activity can have multiple actors. + * The actor MAY be specified using an indirect Link. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-actor + * + * @var string + * | \Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor + * | array + * | array + * | Link + */ + protected string $actor; + + /** + * The indirect object, or target, of the activity. + * The precise meaning of the target is largely dependent on the + * type of action being described but will often be the object of + * the English preposition "to". + * For instance, in the activity "John added a movie to his + * wishlist", the target of the activity is John's wishlist. + * An activity can have more than one target. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-target + * + * @var string + * | ObjectType + * | array + * | Link + * | array + */ + protected string $target; + + /** + * Describes the result of the activity. + * For instance, if a particular action results in the creation of + * a new resource, the result property can be used to describe + * that new resource. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-result + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $result; + + /** + * An indirect object of the activity from which the + * activity is directed. + * The precise meaning of the origin is the object of the English + * preposition "from". + * For instance, in the activity "John moved an item to List B + * from List A", the origin of the activity is "List A". + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-origin + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $origin; + + /** + * One or more objects used (or to be used) in the completion of an + * Activity. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-instrument + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $instrument; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/Activity.php b/plugins/ActivityStreamsTwo/Util/Type/Core/Activity.php new file mode 100644 index 0000000000..8d9219ff48 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/Activity.php @@ -0,0 +1,44 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\Activity is an implementation of one of the + * Activity Streams Core Types. + * + * Activity objects are specializations of the base Object type that + * provide information about actions that have either already occurred, + * are in the process of occurring, or may occur in the future. + * + * @see https://www.w3.org/TR/activitystreams-core/#activities + */ +class Activity extends AbstractActivity +{ + /** + * @var string + */ + protected string $type = 'Activity'; + + /** + * Describes the direct object of the activity. + * For instance, in the activity "John added a movie to his + * wishlist", the object of the activity is the movie added. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-object-term + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $object; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/Collection.php b/plugins/ActivityStreamsTwo/Util/Type/Core/Collection.php new file mode 100644 index 0000000000..fdb47216d0 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/Collection.php @@ -0,0 +1,109 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\Collection is an implementation of one of the + * Activity Streams Core Types. + * + * Collection objects are a specialization of the base Object that serve + * as a container for other Objects or Links. + * + * @see https://www.w3.org/TR/activitystreams-core/#collections + */ +class Collection extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Collection'; + + /** + * @var string + */ + protected string $id; + + /** + * A non-negative integer specifying the total number of objects + * contained by the logical view of the collection. + * This number might not reflect the actual number of items + * serialized within the Collection object instance. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-totalitems + * + * @var int + */ + protected int $totalItems; + + /** + * In a paged Collection, indicates the page that contains the most + * recently updated member items. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-current + * + * @var string + * | Link + * | CollectionPage + * | null + */ + protected string $current; + + /** + * The furthest preceding page of items in the collection. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-last + * + * @var string + * | Link + * | CollectionPage + * | null + */ + protected string $first; + + /** + * The furthest proceeding page of the collection. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-last + * + * @var string + * | Link + * | CollectionPage + * | null + */ + protected string $last; + + /** + * The items contained in a collection. + * The items are considered as unordered. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-items + * + * @var array + * | Link + * | array + * | array + */ + protected array $items = []; + + /** + * The items contained in a collection. + * The items are considered as ordered. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-items + * + * @var array + * | Link + * | array + * | array + */ + protected array $orderedItems = []; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/CollectionPage.php b/plugins/ActivityStreamsTwo/Util/Type/Core/CollectionPage.php new file mode 100644 index 0000000000..a0aec2d4bf --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/CollectionPage.php @@ -0,0 +1,70 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * CollectionPage is an implementation of one + * of the Activity Streams Core Types. + * + * Used to represent distinct subsets of items from a Collection. + * + * @see https://www.w3.org/TR/activitystreams-core/#paging + */ +class CollectionPage extends Collection +{ + /** + * @var string + */ + protected string $type = 'CollectionPage'; + + /** + * @var string + */ + protected string $id; + + /** + * Identifies the Collection to which CollectionPage objects items + * belong. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-partof + * + * @var string + * | Link + * | Collection + * | null + */ + protected string $partOf; + + /** + * Indicates the next page of items. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-next + * + * @var string + * | Link + * | CollectionPage + * | null + */ + protected string $next; + + /** + * Identifies the previous page of items. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-prev + * + * @var string + * | Link + * | CollectionPage + * | null + */ + protected string $prev; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/IntransitiveActivity.php b/plugins/ActivityStreamsTwo/Util/Type/Core/IntransitiveActivity.php new file mode 100644 index 0000000000..7dd68ded16 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/IntransitiveActivity.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\IntransitiveActivity is an implementation of + * one of the Activity Streams Core Types. + * + * IntransitiveActivity objects are specializations of the Activity type + * that represent intransitive actions. IntransitiveActivity objects do + * not have an object property. + * + * @see https://www.w3.org/TR/activitystreams-core/#intransitiveactivities + */ +class IntransitiveActivity extends AbstractActivity +{ + /** + * @var string + */ + protected string $type = 'IntransitiveActivity'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/Link.php b/plugins/ActivityStreamsTwo/Util/Type/Core/Link.php new file mode 100644 index 0000000000..122e55cd77 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/Link.php @@ -0,0 +1,128 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +use Plugin\ActivityStreamsTwo\Util\Type\AbstractObject; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\Link is an implementation of one of the + * Activity Streams Core Types. + * + * A Link describes a qualified, indirect reference to another resource. + * The properties of the Link object are not the properties of the + * referenced resource, but are provided as hints for rendering agents + * to understand how to make use of the resource. + * + * @see https://www.w3.org/TR/activitystreams-core/#link + */ +class Link extends AbstractObject +{ + /** + * @var string + */ + protected string $type = 'Link'; + + /** + * @var string + */ + protected string $id; + + /** + * A simple, human-readable, plain-text name for the object. + * HTML markup MUST NOT be included. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name + * + * @var null|string xsd:string + */ + protected ?string $name; + + /** + * The name MAY be expressed using multiple language-tagged values. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name + * + * @var null|array rdf:langString + */ + protected ?array $nameMap; + + /** + * The target resource pointed to by a Link. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-href + * + * @var null|string + */ + protected ?string $href; + + /** + * Hints as to the language used by the target resource. + * Value MUST be a BCP47 Language-Tag. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-hreflang + * + * @var null|string + */ + protected ?string $hreflang; + + /** + * The MIME media type of the referenced resource. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mediatype + * + * @var null|string + */ + protected ?string $mediaType; + + /** + * A link relation associated with a Link. + * The value MUST conform to both the HTML5 + * and RFC5988 "link relation" definitions. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-rel + * + * @var null|array|string + */ + protected string|array|null $rel; + + /** + * Specifies a hint as to the rendering height + * in device-independentpixels of the linked resource + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-height + * + * @var null|int A non negative integer + */ + protected ?int $height; + + /** + * An entity that provides a preview of this link. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-preview + * + * @var string + * | Object + * | Link + * | null + */ + protected string $preview; + + /** + * On a Link, specifies a hint as to the rendering width in + * device-independent pixels of the linked resource. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-width + * + * @var null|int A non negative integer + */ + protected ?int $width; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/ObjectType.php b/plugins/ActivityStreamsTwo/Util/Type/Core/ObjectType.php new file mode 100644 index 0000000000..ed312ff66c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/ObjectType.php @@ -0,0 +1,440 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +use Plugin\ActivityStreamsTwo\Util\Type\AbstractObject; + +/** + * ObjectType is an implementation of one of the + * Activity Streams Core Types. + * + * The Object is the primary base type for the Activity Streams + * vocabulary. + * + * Note: Object is a reserved keyword in PHP. It has been suffixed with + * 'Type' for this reason. + * + * @see https://www.w3.org/TR/activitystreams-core/#object + */ +class ObjectType extends AbstractObject +{ + /** + * The object's unique global identifier + * + * @see https://www.w3.org/TR/activitypub/#obj-id + * + * @var string + */ + protected string $id; + + /** + * @var string + */ + protected string $type = 'Object'; + + /** + * A resource attached or related to an object that potentially + * requires special handling. + * The intent is to provide a model that is at least semantically + * similar to attachments in email. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attachment + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $attachment; + + /** + * One or more entities to which this object is attributed. + * The attributed entities might not be Actors. For instance, an + * object might be attributed to the completion of another activity. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attributedto + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $attributedTo; + + /** + * One or more entities that represent the total population of + * entities for which the object can considered to be relevant. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audience + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $audience; + + /** + * The content or textual representation of the Object encoded as a + * JSON string. By default, the value of content is HTML. + * The mediaType property can be used in the object to indicate a + * different content type. + * + * The content MAY be expressed using multiple language-tagged + * values. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-content + * + * @var null|string + */ + protected ?string $content; + + /** + * The context within which the object exists or an activity was + * performed. + * The notion of "context" used is intentionally vague. + * The intended function is to serve as a means of grouping objects + * and activities that share a common originating context or + * purpose. An example could be all activities relating to a common + * project or event. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-context + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $context; + + /** + * The content MAY be expressed using multiple language-tagged + * values. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-content + * + * @var null|array + */ + protected ?array $contentMap; + + /** + * A simple, human-readable, plain-text name for the object. + * HTML markup MUST NOT be included. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name + * + * @var null|string xsd:string + */ + protected ?string $name; + + /** + * The name MAY be expressed using multiple language-tagged values. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-name + * + * @var null|array rdf:langString + */ + protected ?array $nameMap; + + /** + * The date and time describing the actual or expected ending time + * of the object. + * When used with an Activity object, for instance, the endTime + * property specifies the moment the activity concluded or + * is expected to conclude. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-endtime + * + * @var null|string + */ + protected ?string $endTime; + + /** + * The entity (e.g. an application) that generated the object. + * + * @var null|string + */ + protected ?string $generator; + + /** + * An entity that describes an icon for this object. + * The image should have an aspect ratio of one (horizontal) + * to one (vertical) and should be suitable for presentation + * at a small size. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-icon + * + * @var string + * | Image + * | Link + * | array + * | array + * | null + */ + protected string $icon; + + /** + * An entity that describes an image for this object. + * Unlike the icon property, there are no aspect ratio + * or display size limitations assumed. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image-term + * + * @var string + * | Image + * | Link + * | array + * | array + * | null + */ + protected string $image; + + /** + * One or more entities for which this object is considered a + * response. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-inreplyto + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $inReplyTo; + + /** + * One or more physical or logical locations associated with the + * object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-location + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $location; + + /** + * An entity that provides a preview of this object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-preview + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $preview; + + /** + * The date and time at which the object was published + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published + * + * @var null|string xsd:dateTime + */ + protected ?string $published; + + /** + * A Collection containing objects considered to be responses to + * this object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-replies + * + * @var string + * | Collection + * | Link + * | null + */ + protected string $replies; + + /** + * The date and time describing the actual or expected starting time + * of the object. + * When used with an Activity object, for instance, the startTime + * property specifies the moment the activity began + * or is scheduled to begin. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-starttime + * + * @var null|string xsd:dateTime + */ + protected ?string $startTime; + + /** + * A natural language summarization of the object encoded as HTML. + * Multiple language tagged summaries MAY be provided. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary + * + * @var string + * | ObjectType + * | Link + * | null + */ + protected string $summary; + + /** + * The content MAY be expressed using multiple language-tagged + * values. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-summary + * + * @var null|array + */ + protected mixed $summaryMap; + + /** + * One or more "tags" that have been associated with an objects. + * A tag can be any kind of Object. + * The key difference between attachment and tag is that the former + * implies association by inclusion, while the latter implies + * associated by reference. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tag + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $tag; + + /** + * The date and time at which the object was updated + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-updated + * + * @var null|string xsd:dateTime + */ + protected ?string $updated; + + /** + * One or more links to representations of the object. + * + * @var string + * | array + * | Link + * | array + * | null + */ + protected string $url; + + /** + * An entity considered to be part of the public primary audience + * of an Object + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-to + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $to; + + /** + * An Object that is part of the private primary audience of this + * Object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bto + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $bto; + + /** + * An Object that is part of the public secondary audience of this + * Object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-cc + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $cc; + + /** + * One or more Objects that are part of the private secondary + * audience of this Object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-bcc + * + * @var string + * | ObjectType + * | Link + * | array + * | array + * | null + */ + protected string $bcc; + + /** + * The MIME media type of the value of the content property. + * If not specified, the content property is assumed to contain + * text/html content. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mediatype + * + * @var null|string + */ + protected ?string $mediaType; + + /** + * When the object describes a time-bound resource, such as an audio + * or video, a meeting, etc, the duration property indicates the + * object's approximate duration. + * The value MUST be expressed as an xsd:duration as defined by + * xmlschema11-2, section 3.3.6 (e.g. a period of 5 seconds is + * represented as "PT5S"). + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration + * + * @var null|string + */ + protected ?string $duration; + + /** + * Intended to convey some sort of source from which the content + * markup was derived, as a form of provenance, or to support + * future editing by clients. + * + * @see https://www.w3.org/TR/activitypub/#source-property + * + * @var ObjectType + */ + protected ObjectType $source; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/OrderedCollection.php b/plugins/ActivityStreamsTwo/Util/Type/Core/OrderedCollection.php new file mode 100644 index 0000000000..7d58ae708a --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/OrderedCollection.php @@ -0,0 +1,29 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollection is an implementation of one + * of the Activity Streams Core Types. + * + * A subtype of Collection in which members of the logical collection + * are assumed to always be strictly ordered. + * + * @see https://www.w3.org/TR/activitystreams-core/#collections + */ +class OrderedCollection extends Collection +{ + /** + * @var string + */ + protected string $type = 'OrderedCollection'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Core/OrderedCollectionPage.php b/plugins/ActivityStreamsTwo/Util/Type/Core/OrderedCollectionPage.php new file mode 100644 index 0000000000..86b5e76217 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Core/OrderedCollectionPage.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Core; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollection is an implementation of one + * of the Activity Streams Core Types. + * + * The OrderedCollectionPage type extends from both CollectionPage and + * OrderedCollection. In addition to the properties inherited from each + * of those, the OrderedCollectionPage may contain an additional + * startIndex property whose value indicates the relative index position + * of the first item contained by the page within the OrderedCollection + * to which the page belongs. + * + * @see https://www.w3.org/TR/activitystreams-core/#paging + */ +class OrderedCollectionPage extends CollectionPage +{ + /** + * @var string + */ + protected string $type = 'OrderedCollectionPage'; + + /** + * A non-negative integer value identifying the relative position + * within the logical view of a strictly ordered collection. + * + * @var int + */ + protected int $startIndex; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/AbstractActor.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/AbstractActor.php new file mode 100644 index 0000000000..35fb4f27a6 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/AbstractActor.php @@ -0,0 +1,126 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollection; + +/** + * \ActivityPhp\Type\Extended\AbstractActor is an abstract class that + * provides dedicated Actor's properties + */ +abstract class AbstractActor extends ObjectType +{ + /** + * A reference to an ActivityStreams OrderedCollection comprised of + * all the messages received by the actor. + * + * @see https://www.w3.org/TR/activitypub/#inbox + * + * @var OrderedCollection + * | \ActivityPhp\Type\Core\OrderedCollectionPage + * | null + */ + protected OrderedCollection $inbox; + + /** + * A reference to an ActivityStreams OrderedCollection comprised of + * all the messages produced by the actor. + * + * @see https://www.w3.org/TR/activitypub/#outbox + * + * @var OrderedCollection + * | \ActivityPhp\Type\Core\OrderedCollectionPage + * | null + */ + protected OrderedCollection $outbox; + + /** + * A link to an ActivityStreams collection of the actors that this + * actor is following. + * + * @see https://www.w3.org/TR/activitypub/#following + * + * @var string + */ + protected string $following; + + /** + * A link to an ActivityStreams collection of the actors that + * follow this actor. + * + * @see https://www.w3.org/TR/activitypub/#followers + * + * @var string + */ + protected string $followers; + + /** + * A link to an ActivityStreams collection of objects this actor has + * liked. + * + * @see https://www.w3.org/TR/activitypub/#liked + * + * @var string + */ + protected string $liked; + + /** + * A list of supplementary Collections which may be of interest. + * + * @see https://www.w3.org/TR/activitypub/#streams-property + * + * @var array + */ + protected array $streams = []; + + /** + * A short username which may be used to refer to the actor, with no + * uniqueness guarantees. + * + * @see https://www.w3.org/TR/activitypub/#preferredUsername + * + * @var null|string + */ + protected ?string $preferredUsername; + + /** + * A JSON object which maps additional typically server/domain-wide + * endpoints which may be useful either for this actor or someone + * referencing this actor. This mapping may be nested inside the + * actor document as the value or may be a link to a JSON-LD + * document with these properties. + * + * @see https://www.w3.org/TR/activitypub/#endpoints + * + * @var null|array|string + */ + protected string|array|null $endpoints; + + /** + * It's not part of the ActivityPub protocol, but it's a quite common + * practice handling an actor public key with a publicKey array: + * [ + * 'id' => 'https://my-example.com/actor#main-key' + * 'owner' => 'https://my-example.com/actor', + * 'publicKeyPem' => '-----BEGIN PUBLIC KEY----- + * MIIBI [...] + * DQIDAQAB + * -----END PUBLIC KEY-----' + * ] + * + * @see https://www.w3.org/wiki/SocialCG/ActivityPub/Authentication_Authorization#Signing_requests_using_HTTP_Signatures + * + * @var null|array|string + */ + protected string|array|null $publicKey; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Accept.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Accept.php new file mode 100644 index 0000000000..4121e52222 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Accept.php @@ -0,0 +1,32 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Accept is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor accepts the object. The target property can + * be used in certain circumstances to indicate the context into which + * the object has been accepted. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accept + */ +class Accept extends Activity +{ + /** + * @var string + */ + protected string $type = 'Accept'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Announce.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Announce.php new file mode 100644 index 0000000000..25b2f5984f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Announce.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Announce is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is calling the target's attention the + * object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-announce + */ +class Announce extends Activity +{ + /** + * @var string + */ + protected string $type = 'Announce'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Block.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Block.php new file mode 100644 index 0000000000..947a6ff15b --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Block.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Block is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is blocking the object. Blocking is a + * stronger form of Ignore. The typical use is to support social systems + * that allow one user to block activities or content of other users. + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-block + */ +class Block extends Ignore +{ + /** + * @var string + */ + protected string $type = 'Block'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Create.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Create.php new file mode 100644 index 0000000000..15f63dd924 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Create.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Create is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor has created the object. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-create + */ +class Create extends Activity +{ + /** + * @var string + */ + protected string $type = 'Create'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Delete.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Delete.php new file mode 100644 index 0000000000..cd6f74eb52 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Delete.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Delete is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor has deleted the object. If specified, the + * origin indicates the context from which the object was deleted. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-delete + */ +class Delete extends Activity +{ + /** + * @var string + */ + protected string $type = 'Delete'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Follow.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Follow.php new file mode 100644 index 0000000000..e10a9b7e84 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Follow.php @@ -0,0 +1,34 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Follow is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is "following" the object. Following is + * defined in the sense typically used within Social systems in which + * the actor is interested in any activity performed by or on the + * object. + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-follow + */ +class Follow extends Activity +{ + /** + * @var string + */ + protected string $type = 'Follow'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Ignore.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Ignore.php new file mode 100644 index 0000000000..ab203f2a55 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Ignore.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \ActivityPhp\Type\Extended\Activity\Ignore is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is ignoring the object. + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-ignore + */ +class Ignore extends Activity +{ + /** + * @var string + */ + protected string $type = 'Ignore'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Join.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Join.php new file mode 100644 index 0000000000..11f7b27ace --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Join.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Join is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor has joined the object. + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-join + */ +class Join extends Activity +{ + /** + * @var string + */ + protected string $type = 'Join'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Leave.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Leave.php new file mode 100644 index 0000000000..5ab7e1c344 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Leave.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Leave is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor has left the object. + * The target and origin typically have no meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-leave + */ +class Leave extends Activity +{ + /** + * @var string + */ + protected string $type = 'Leave'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Like.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Like.php new file mode 100644 index 0000000000..98f3b14fb3 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Like.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Like is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor likes, recommends or endorses the object. + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-like + */ +class Like extends Activity +{ + /** + * @var string + */ + protected string $type = 'Like'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Question.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Question.php new file mode 100644 index 0000000000..87f72453bd --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Question.php @@ -0,0 +1,76 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\IntransitiveActivity; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Question is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a question being asked. Question objects are an extension + * of IntransitiveActivity. That is, the Question object is an Activity, + * but the direct object is the question itself, and therefore it would + * not contain an object property. + * + * Either of the anyOf and oneOf properties MAY be used to express + * possible answers, but a Question object MUST NOT have both properties + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-move + */ +class Question extends IntransitiveActivity +{ + /** + * @var string + */ + protected string $type = 'Question'; + + /** + * An exclusive option for a Question + * Use of oneOf implies that the Question can have only a + * single answer. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-oneof + * + * @var array + * | array<\Plugin\ActivityStreamsTwo\Util\Type\Core\Link> + * | null + */ + protected array $oneOf; + + /** + * An inclusive option for a Question. + * Use of anyOf implies that the Question can have multiple answers. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-anyof + * + * @var array + * | array<\Plugin\ActivityStreamsTwo\Util\Type\Core\Link> + * | null + */ + protected array $anyOf; + + /** + * Indicates that a question has been closed, and answers are no + * longer accepted. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-closed + * + * @var ObjectType + * | \Plugin\ActivityStreamsTwo\Util\Type\Core\Link + * | \DateTime + * | bool + * | null + */ + protected ObjectType $closed; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Reject.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Reject.php new file mode 100644 index 0000000000..6d7e2c7ac6 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Reject.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Reject is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is rejecting the object. + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-reject + */ +class Reject extends Activity +{ + /** + * @var string + */ + protected string $type = 'Reject'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Remove.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Remove.php new file mode 100644 index 0000000000..2d536ce88f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Remove.php @@ -0,0 +1,32 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Remove is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is removing the object. + * If specified, the origin indicates the context from which the object + * is being removed. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-remove + */ +class Remove extends Activity +{ + /** + * @var string + */ + protected string $type = 'Remove'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Undo.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Undo.php new file mode 100644 index 0000000000..38c95d225d --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Undo.php @@ -0,0 +1,36 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Undo is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor is undoing the object. In most cases, the + * object will be an Activity describing some previously performed + * action (for instance, a person may have previously "liked" an article + * but, for whatever reason, might choose to undo that like at some + * later point in time). + * + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-undo + */ +class Undo extends Activity +{ + /** + * @var string + */ + protected string $type = 'Undo'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Update.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Update.php new file mode 100644 index 0000000000..0ec743e904 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Activity/Update.php @@ -0,0 +1,34 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Update is an implementation of + * one of the Activity Streams Extended Types. + * + * Indicates that the actor has updated the object. Note, however, that + * this vocabulary does not define a mechanism for describing the actual + * set of modifications made to object. + * + * The target and origin typically have no defined meaning. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-update + */ +class Update extends Activity +{ + /** + * @var string + */ + protected string $type = 'Update'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Application.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Application.php new file mode 100644 index 0000000000..c1a969a0b0 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Application.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor; + +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor\Application is an implementation of + * one of the Activity Streams Extended Types. + * + * Describes a software application. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-application + */ +class Application extends AbstractActor +{ + /** + * @var string + */ + protected string $type = 'Application'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Group.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Group.php new file mode 100644 index 0000000000..d3b275de30 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Group.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor; + +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor\Group is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a formal or informal collective of Actors. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-group + */ +class Group extends AbstractActor +{ + /** + * @var string + */ + protected string $type = 'Group'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Organization.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Organization.php new file mode 100644 index 0000000000..70dfc2239e --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Organization.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor; + +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor\Organization is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a formal or informal collective of Actors. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-organization + */ +class Organization extends AbstractActor +{ + /** + * @var string + */ + protected string $type = 'Organization'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Person.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Person.php new file mode 100644 index 0000000000..396167adf6 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Person.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor; + +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor\Person is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents an individual person. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-person + */ +class Person extends AbstractActor +{ + /** + * @var string + */ + protected string $type = 'Person'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Service.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Service.php new file mode 100644 index 0000000000..82d51cde4f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Actor/Service.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor; + +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Actor\Service is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a service of any kind. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-service + */ +class Service extends AbstractActor +{ + /** + * @var string + */ + protected string $type = 'Service'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Article.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Article.php new file mode 100644 index 0000000000..4723731905 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Article.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Article is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents any kind of multi-paragraph written work. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-article + */ +class Article extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Article'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Audio.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Audio.php new file mode 100644 index 0000000000..4215f4a9e0 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Audio.php @@ -0,0 +1,28 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Audio is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a document of any kind. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-audio + */ +class Audio extends Document +{ + /** + * @var string + */ + protected string $type = 'Audio'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Document.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Document.php new file mode 100644 index 0000000000..4b57cacea7 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Document.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Document is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents an audio document of any kind. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-document + */ +class Document extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Document'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Event.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Event.php new file mode 100644 index 0000000000..757e2d7096 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Event.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Event is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents any kind of event. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-event + */ +class Event extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Event'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Image.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Image.php new file mode 100644 index 0000000000..02328e18a3 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Image.php @@ -0,0 +1,28 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Image is an implementation of + * one of the Activity Streams Extended Types. + * + * An image document of any kind. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-image + */ +class Image extends Document +{ + /** + * @var string + */ + protected string $type = 'Image'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Mention.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Mention.php new file mode 100644 index 0000000000..54cbc23d08 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Mention.php @@ -0,0 +1,30 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Mention is an implementation of + * one of the Activity Streams Extended Types. + * + * A specialized Link that represents an @mention. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-mention + */ +class Mention extends Link +{ + /** + * @var string + */ + protected string $type = 'Mention'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Note.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Note.php new file mode 100644 index 0000000000..1f1c6203ea --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Note.php @@ -0,0 +1,31 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Note is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a short written work typically less than a single + * paragraph in length. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-note + */ +class Note extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Note'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Page.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Page.php new file mode 100644 index 0000000000..9ccf8acee0 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Page.php @@ -0,0 +1,28 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Page is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a Web Page. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-page + */ +class Page extends Document +{ + /** + * @var string + */ + protected string $type = 'Page'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Place.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Place.php new file mode 100644 index 0000000000..79a016f140 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Place.php @@ -0,0 +1,96 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Place is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a logical or physical location. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-place + */ +class Place extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Place'; + + /** + * Indicates the accuracy of position coordinates on a Place + * objects. Expressed in properties of percentage. + * e.g. "94.0" means "94.0% accurate". + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-accuracy + * + * @var null|float + */ + protected ?float $accuracy; + + /** + * The altitude of a place. + * The measurement units is indicated using the units' property. + * If units is not specified, the default is assumed to be "m" + * indicating meters. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-altitude + * + * @var null|float + */ + protected ?float $altitude; + + /** + * The latitude of a place. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-latitude + * + * @var null|float|int + */ + protected int|null|float $latitude; + + /** + * The longitude of a place. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-longitude + * + * @var null|float|int + */ + protected int|null|float $longitude; + + /** + * The radius from the given latitude and longitude for a Place. + * The units are expressed by the units' property. + * If units is not specified, the default is assumed to be "m" + * indicating "meters". + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-radius + * + * @var null|float|int + */ + protected int|null|float $radius; + + /** + * Specifies the measurement units for the radius and altitude + * properties on a Place object. + * If not specified, the default is assumed to be "m" for "meters". + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-units + * + * "cm" | " feet" | " inches" | " km" | " m" | " miles" | xsd:anyURI + * + * @var string + */ + protected string $units; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Profile.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Profile.php new file mode 100644 index 0000000000..23bfad8f78 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Profile.php @@ -0,0 +1,40 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Profile is an implementation of + * one of the Activity Streams Extended Types. + * + * A Profile is a content object that describes another Object, + * typically used to describe Actor Type objects. + * The describes property is used to reference the object being + * described by the profile. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-profile + */ +class Profile extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Profile'; + + /** + * Identify the object described by the Profile. + * + * @var ObjectType + */ + protected ObjectType $describes; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Tombstone.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Tombstone.php new file mode 100644 index 0000000000..b8757f9959 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Tombstone.php @@ -0,0 +1,50 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Tombstone is an implementation of + * one of the Activity Streams Extended Types. + * + * A Tombstone represents a content object that has been deleted. It can + * be used in Collections to signify that there used to be an object at + * this position, but it has been deleted. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-tombstone + */ +class Tombstone extends ObjectType +{ + /** + * @var string + */ + protected string $type = 'Tombstone'; + + /** + * The type of the object that was deleted. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-formertype + * + * @var null|string + */ + protected ?string $formerType; + + /** + * A timestamp for when the object was deleted. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-deleted + * + * @var null|string xsd:dateTime formatted + */ + protected ?string $deleted; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Video.php b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Video.php new file mode 100644 index 0000000000..c1c24a347e --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Extended/Object/Video.php @@ -0,0 +1,28 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Extended\Object; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Video is an implementation of + * one of the Activity Streams Extended Types. + * + * Represents a video document of any kind. + * + * @see https://www.w3.org/TR/activitystreams-vocabulary/#dfn-video + */ +class Video extends Document +{ + /** + * @var string + */ + protected string $type = 'Video'; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/TypeResolver.php b/plugins/ActivityStreamsTwo/Util/Type/TypeResolver.php new file mode 100644 index 0000000000..7977b8d78d --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/TypeResolver.php @@ -0,0 +1,149 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type; + +use Exception; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\TypeResolver is an abstract class for + * resolving class names called by their short names (AS types). + */ +abstract class TypeResolver +{ + /** + * A list of core types + * + * @var array + */ + protected static array $coreTypes = [ + 'Activity', 'Collection', 'CollectionPage', + 'IntransitiveActivity', 'Link', 'ObjectType', + 'OrderedCollection', 'OrderedCollectionPage', + 'Object', + ]; + + /** + * A list of actor types + * + * @var array + */ + protected static array $actorTypes = [ + 'Application', 'Group', 'Organization', 'Person', 'Service', + ]; + + /** + * A list of activity types + * + * @var array + */ + protected static array $activityTypes = [ + 'Accept', 'Add', 'Announce', 'Block', + 'Create', 'Delete', 'Follow', 'Ignore', + 'Invite', 'Join', 'Leave', 'Like', + 'Question', 'Reject', 'Remove', 'Undo', + ]; + + /** + * A list of object types + * + * @var array + */ + protected static array $objectTypes = [ + 'Article', 'Audio', 'Document', 'Event', 'Image', + 'Mention', 'Note', 'Page', 'Place', 'Profile', + 'Tombstone', 'Video', + ]; + + /** + * Get namespaced class for a given short type + * + * @param string $type + * + * @throws Exception + * + * @return string Related namespace + * @throw \Exception if a namespace was not found. + */ + public static function getClass(string $type): string + { + $ns = __NAMESPACE__; + + if ($type == 'Object') { + $type .= 'Type'; + } + + switch ($type) { + case in_array($type, self::$coreTypes): + $ns .= '\Core'; + break; + case in_array($type, self::$activityTypes): + $ns .= '\Extended\Activity'; + break; + case in_array($type, self::$actorTypes): + $ns .= '\Extended\Actor'; + break; + case in_array($type, self::$objectTypes): + $ns .= '\Extended\Object'; + break; + default: + throw new Exception( + "Undefined scope for type '{$type}'" + ); + } + + return $ns . '\\' . $type; + } + + /** + * Validate an object pool type with type attribute + * + * @param object $item + * @param string $poolname An expected pool name + * + * @return bool + */ + public static function isScope(object $item, string $poolname = 'all'): bool + { + if (!is_object($item) + || !isset($item->type) + || !is_string($item->type) + ) { + return false; + } + + return match (strtolower($poolname)) { + 'all' => self::exists($item->type), + 'actor' => in_array($item->type, self::$actorTypes), + default => false, + }; + } + + /** + * Verify that a type exists + * + * @param string $name + * + * @return bool + */ + public static function exists(string $name): bool + { + return in_array( + $name, + array_merge( + self::$coreTypes, + self::$activityTypes, + self::$actorTypes, + self::$objectTypes + ) + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Util.php b/plugins/ActivityStreamsTwo/Util/Type/Util.php new file mode 100644 index 0000000000..25dfb6cc48 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Util.php @@ -0,0 +1,566 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type; + +use DateInterval; +use DateTime; +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Util is an abstract class for + * supporting validators checks & transformations. + */ +abstract class Util +{ + /** + * Allowed units + * + * @var array + */ + protected static array $units = [ + 'cm', 'feet', 'inches', 'km', 'm', 'miles', + ]; + + /** + * Transform an array into an ActivityStreams type + * + * @param array $item + * + * @throws Exception + * + * @return AbstractObject|array An ActivityStreams + * type or given array if type key is not defined. + */ + public static function arrayToType(array $item): AbstractObject|array + { + // Maybe an array representing an AS object + // It must have a type key + if (isset($item['type'])) { + return Type::create($item['type'], $item); + } + + return $item; + } + + /** + * Validate an URL + * + * @param mixed $value + * + * @return bool + */ + public static function validateUrl(mixed $value): bool + { + return is_string($value) + && filter_var($value, FILTER_VALIDATE_URL) !== false + && in_array( + parse_url($value, PHP_URL_SCHEME), + ['http', 'https', 'magnet'] + ); + } + + /** + * Validate a magnet link + * + * @param mixed $value + * + * @return bool + * + * @see https://en.wikipedia.org/wiki/Magnet_URI_scheme + * + * @todo Make a better validation as xs is not the only parameter + */ + public static function validateMagnet(mixed $value): bool + { + return is_string($value) + && strlen($value) < 262144 + && preg_match( + '#^magnet:\?xs=(https?)://.*$#iu', + urldecode($value) + + ); + } + + /** + * Validate an OStatus tag string + * + * @param mixed $value + * + * @return bool + */ + public static function validateOstatusTag(mixed $value): bool + { + return is_string($value) + && strlen($value) < 262144 + && preg_match( + '#^tag:([\w\-\.]+),([\d]{4}-[\d]{2}-[\d]{2}):([\w])+Id=([\d]+):objectType=([\w]+)#iu', + $value + ); + } + + /** + * Validate a rel attribute value. + * + * @see https://tools.ietf.org/html/rfc5988 + * + * @param string $value + * + * @return bool + */ + public static function validateRel(string $value): bool + { + return is_string($value) + && preg_match("/^[^\\s\r\n\\,]+\\z/i", $value); + } + + /** + * Validate a non negative integer. + * + * @param int $value + * + * @return bool + */ + public static function validateNonNegativeInteger(int $value): bool + { + return is_int($value) + && $value >= 0; + } + + /** + * Validate a non negative number. + * + * @param float|int $value + * + * @return bool + */ + public static function validateNonNegativeNumber(float|int $value): bool + { + return is_numeric($value) + && $value >= 0; + } + + /** + * Validate units format. + * + * @param string $value + * + * @return bool + */ + public static function validateUnits(string $value): bool + { + if (is_string($value)) { + if (in_array($value, self::$units) + || self::validateUrl($value) + ) { + return true; + } + } + + return false; + } + + /** + * Validate an Object type + * + * @param object $item + * + * @throws Exception + * + * @return bool + */ + public static function validateObject(object $item): bool + { + return self::hasProperties($item, ['type']) + && is_string($item->type) + && $item->type === 'Object'; + } + + /** + * Decode a JSON string + * + * @throws Exception if JSON decoding process has failed + */ + public static function decodeJson(string $value): array + { + $json = json_decode($value, true); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new Exception( + 'JSON decoding failed for string: ' . $value + ); + } + + return $json; + } + + /** + * Checks that all properties exist for a stdClass + * + * @param object $item + * @param array $properties + * @param bool $strict If true throws an \Exception, + * otherwise, returns false + * + * @throws Exception if a property is not set + * + * @return bool + */ + public static function hasProperties( + object $item, + array $properties, + bool $strict = false + ): bool { + foreach ($properties as $property) { + if (!property_exists($item, $property)) { + if ($strict) { + throw new Exception( + sprintf( + 'Attribute "%s" MUST be set for item: %s', + $property, + print_r($item, true) + ) + ); + } + + return false; + } + } + + return true; + } + + /** + * Validate a reference with a Link or an Object with a URL + * + * @param object $item + * + * @throws Exception + * + * @return bool + */ + public static function isLinkOrUrlObject(object $item): bool + { + self::hasProperties($item, ['type'], true); + + // Validate Link type + if ($item->type === 'Link') { + return self::validateLink($item); + } + + // Validate Object type + self::hasProperties($item, ['url'], true); + + return self::validateUrl($item->url); + } + + /** + * Validate a reference as Link + * + * @param array|object $item + * + * @throws Exception + * + * @return bool + */ + public static function validateLink(object|array $item): bool + { + if (is_array($item)) { + $item = (object) $item; + } + + if (!is_object($item)) { + return false; + } + + self::hasProperties($item, ['type'], true); + + // Validate Link type + if ($item->type !== 'Link') { + return false; + } + + // Validate Object type + self::hasProperties($item, ['href'], true); + + return self::validateUrl($item->href) + || self::validateMagnet($item->href); + } + + /** + * Validate a datetime + * + * @param mixed $value + */ + public static function validateDatetime($value): bool + { + if (!is_string($value) + || !preg_match( + '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.*)$/', + $value + ) + ) { + return false; + } + + try { + $dt = new DateTime($value); + return true; + } catch (Exception $e) { + return false; + } + } + + /** + * Check that container class is a subclass of a given class + * + * @param object $container + * @param array|string $classes + * @param bool $strict If true, throws an exception + * + * @throws Exception + * + * @return bool + */ + public static function subclassOf(object $container, array|string $classes, bool $strict = false): bool + { + if (!is_array($classes)) { + $classes = [$classes]; + } + + foreach ($classes as $class) { + if (get_class($container) === $class + || is_subclass_of($container, $class) + ) { + return true; + } + } + + if ($strict) { + throw new Exception( + sprintf( + 'Class "%s" MUST be a subclass of "%s"', + get_class($container), + implode(', ', $classes) + ) + ); + } + + return false; + } + + /** + * Checks that a numeric value is part of a range. + * If a minimal value is null, value has to be inferior to max value + * If a maximum value is null, value has to be superior to min value + * + * @param float|int $value + * @param null|float|int $min + * @param null|float|int $max + * + * @return bool + */ + public static function between(float|int $value, float|int|null $min, float|int|null $max): bool + { + if (!is_numeric($value)) { + return false; + } + + return match (true) { + is_null($min) && is_null($max) => false, + is_null($min) => $value <= $max, + is_null($max) => $value >= $min, + default => $value >= $min + && $value <= $max, + }; + } + + /** + * Check that a given string is a valid XML Schema xsd:duration + * + * @param string $duration + * @param bool $strict If true, throws an exception + * + * @throws Exception + * + * @return bool + */ + public static function isDuration(string $duration, bool $strict = false): bool + { + try { + new DateInterval($duration); + return true; + } catch (Exception $e) { + if ($strict) { + throw new Exception( + sprintf( + 'Duration "%s" MUST respect xsd:duration', + $duration + ) + ); + } + } + + return false; + } + + /** + * Checks that it's an object type + * + * @param object $item + * + * @return bool + */ + public static function isObjectType(object $item): bool + { + return TypeResolver::isScope($item); + } + + /** + * Checks that it's an actor type + * + * @param object $item + * + * @return bool + */ + public static function isActorType(object $item): bool + { + return TypeResolver::isScope($item, 'actor'); + } + + /** + * Validate an object type with type attribute + * + * @param object $item + * @param string $type An expected type + * + * @return bool + */ + public static function isType(object $item, string $type): bool + { + // Validate that container is a certain type + if (!is_object($item)) { + return false; + } + + if (property_exists($item, 'type') + && is_string($item->type) + && $item->type === $type + ) { + return true; + } + + return false; + } + + /** + * Validate a BCP 47 language value + * + * @param string $value + * + * @return bool + */ + public static function validateBcp47(string $value): bool + { + return is_string($value) + && preg_match( + '/^(((en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((([A-Za-z]{2,3}(-([A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-([A-Za-z]{4}))?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-([0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(x(-[A-Za-z0-9]{1,8})+))?)|(x(-[A-Za-z0-9]{1,8})+))$/', + $value + ); + } + + /** + * Validate a plain text value + * + * @param string $value + * + * @return bool + */ + public static function validatePlainText(string $value): bool + { + return is_string($value) + && preg_match( + '/^([^<]+)$/', + $value + ); + } + + /** + * Validate mediaType format + * + * @param string $value + * + * @return bool + */ + public static function validateMediaType(string $value): bool + { + return is_string($value) + && preg_match( + '#^(([\w]+[\w\-]+[\w+])/(([\w]+[\w\-\.\+]+[\w]+)|(\*));?)+$#', + $value + ); + } + + /** + * Validate a Collection type + * + * @param object $item + * + * @throws Exception + * + * @return bool + */ + public static function validateCollection(object $item): bool + { + if (is_scalar($item)) { + return false; + } + + if (!is_object($item)) { + $item = (object) $item; + } + + self::hasProperties( + $item, + [/*totalItems', 'current', 'first', 'last', */ 'items'], + true + ); + + return true; + } + + /** + * Validate a CollectionPage type + * + * @param object $item + * + * @throws Exception + * + * @return bool + */ + public static function validateCollectionPage(object $item): bool + { + + // Must be a Collection + if (!self::validateCollection($item)) { + return false; + } + + self::hasProperties( + $item, + ['partOf'/*, 'next', 'prev'*/], + true + ); + + return true; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator.php new file mode 100644 index 0000000000..b5aaf44257 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator.php @@ -0,0 +1,100 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type; + +use Exception; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator is an abstract class for + * attribute validation. + */ +abstract class Validator +{ + /** + * Contains all custom validators + * + * @var array + * + * [ 'attributeName' => CustomValidatorClassName::class ] + */ + protected static array $validators = []; + + /** + * Validate an attribute value for given attribute name and + * container object. + * + * @param string $name + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception if $container is not an object + * + * @return bool + */ + public static function validate(string $name, mixed $value, mixed $container): bool + { + if (!is_object($container)) { + throw new Exception( + 'Given container is not an object' + ); + } + + // Perform validation + if (isset(self::$validators[$name])) { + return self::$validators[$name]->validate( + $value, + $container + ); + } + + // Try to load a default validator + $validatorName = sprintf( + '\Plugin\ActivityStreamsTwo\Util\Type\Validator\%sValidator', + ucfirst($name) + ); + + if (class_exists($validatorName)) { + self::add($name, $validatorName); + return self::validate($name, $value, $container); + } + + // There is no validator for this attribute + return true; + } + + /** + * Add a new validator in the pool. + * It checks that it implements Validator\Interface + * + * @param string $name An attribute name to validate. + * @param object|string $class A validator class name + * + * @throws Exception if validator class does not implement + * \Plugin\ActivityStreamsTwo\Util\Type\Helper\ValidatorInterface + */ + public static function add(string $name, object|string $class): void + { + $validator = new $class(); + + if (!($validator instanceof ValidatorInterface)) { + throw new Exception( + sprintf( + 'Validator "%s" MUST implement "%s" interface', + get_class($validator), + ValidatorInterface::class + ) + ); + } + + self::$validators[$name] = $validator; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/AccuracyValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/AccuracyValidator.php new file mode 100644 index 0000000000..bd2c486b2c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/AccuracyValidator.php @@ -0,0 +1,36 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\AccuracyValidator is a dedicated + * validator for accuracy attribute. + */ +class AccuracyValidator implements ValidatorInterface +{ + /** + * Validate an ACCURACY attribute value + * + * @param mixed $value + * @param mixed $container An object + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return is_numeric($value) + && (float) $value >= 0 + && (float) $value <= 100.0; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ActorValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ActorValidator.php new file mode 100644 index 0000000000..578a786538 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ActorValidator.php @@ -0,0 +1,116 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Collection; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ActorValidator is a dedicated + * validator for actor attribute. + */ +class ActorValidator implements ValidatorInterface +{ + /** + * Validate an ACTOR attribute value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Can be an indirect link + if (is_string($value) && Util::validateUrl($value)) { + return true; + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // A collection + if (is_array($value)) { + return $this->validateObjectCollection($value); + } + + // Must be an object + if (!is_object($value)) { + return false; + } + + // A single actor + return $this->validateObject($value); + } + + /** + * Validate an Actor object type + * + * @param array|object $item + * + * @throws Exception + * + * @return bool + */ + protected function validateObject(object|array $item): bool + { + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + Util::subclassOf( + $item, [ + AbstractActor::class, + Link::class, + Collection::class, + ], + true + ); + + return true; + } + + /** + * Validate a list of object + * Collection can contain: + * - Indirect URL + * - An actor object + * + * @throws Exception + * @throws Exception + */ + protected function validateObjectCollection(array $collection): bool + { + foreach ($collection as $item) { + if (is_array($item) && $this->validateObject($item)) { + continue; + } + if (is_object($item) && $this->validateObject($item)) { + continue; + } + if (is_string($item) && Util::validateUrl($item)) { + continue; + } + + return false; + } + + return count($collection) > 0; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/AltitudeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/AltitudeValidator.php new file mode 100644 index 0000000000..1aed949246 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/AltitudeValidator.php @@ -0,0 +1,38 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\AltitudeValidator is a dedicated + * validator for altitude attribute. + */ +class AltitudeValidator implements ValidatorInterface +{ + /** + * Validate an ALTITUDE attribute value + * + * @param mixed $value + * @param mixed $container An object + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + if (is_float($value) || is_int($value)) { + return true; + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/AnyOfValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/AnyOfValidator.php new file mode 100644 index 0000000000..40c7d5848e --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/AnyOfValidator.php @@ -0,0 +1,57 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Question; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\AnyOfValidator is a dedicated + * validator for anyOf attribute. + */ +class AnyOfValidator extends ValidatorTools +{ + /** + * Validate an ANYOF attribute value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + * + * @todo Choices can contain Indirect references. + * This validation should validate this kind of usage. + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Question type + Util::subclassOf($container, Question::class, true); + + // A collection + if (!is_array($value)) { + return false; + } + + if (!count($value)) { + return false; + } + + return $this->validateObjectCollection( + $value, + $this->getQuestionAnswerValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/AttachmentValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/AttachmentValidator.php new file mode 100644 index 0000000000..fb10c7dc01 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/AttachmentValidator.php @@ -0,0 +1,45 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\AttachmentValidator is a dedicated + * validator for attachment attribute. + */ +class AttachmentValidator extends ValidatorTools +{ + /** + * Validate an attachment value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + if (is_array($value) && !count($value)) { + return true; + } + + return $this->validateListOrObject( + $value, + $container, + $this->getAttachmentValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/AttributedToValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/AttributedToValidator.php new file mode 100644 index 0000000000..24aba6aff1 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/AttributedToValidator.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\AttributedToValidator is a dedicated + * validator for attributedTo attribute. + */ +class AttributedToValidator extends ValidatorTools +{ + /** + * Validate an attributedTo value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateListOrObject( + $value, + $container, + $this->getCollectionActorsValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/AudienceValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/AudienceValidator.php new file mode 100644 index 0000000000..67a7fe9e85 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/AudienceValidator.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\AudienceValidator is a dedicated + * validator for audience attribute. + */ +class AudienceValidator extends ValidatorTools +{ + /** + * Validate an audience value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateListOrObject( + $value, + $container, + $this->getLinkOrNamedObjectValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/BccValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/BccValidator.php new file mode 100644 index 0000000000..658e9c6f8f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/BccValidator.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\BccValidator is a dedicated + * validator for bcc attribute. + */ +class BccValidator extends ValidatorTools +{ + /** + * Validate a bcc value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateListOrObject( + $value, + $container, + $this->getLinkOrUrlObjectValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/BtoValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/BtoValidator.php new file mode 100644 index 0000000000..9219f61941 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/BtoValidator.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\BtoValidator is a dedicated + * validator for bto attribute. + */ +class BtoValidator extends ValidatorTools +{ + /** + * Validate a bto value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateListOrObject( + $value, + $container, + $this->getLinkOrUrlObjectValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/CcValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/CcValidator.php new file mode 100644 index 0000000000..7182365ec8 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/CcValidator.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\CcValidator is a dedicated + * validator for cc attribute. + */ +class CcValidator extends ValidatorTools +{ + /** + * Validate a cc value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateListOrObject( + $value, + $container, + $this->getLinkOrUrlObjectValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ClosedValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ClosedValidator.php new file mode 100644 index 0000000000..c2448703f2 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ClosedValidator.php @@ -0,0 +1,69 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Activity\Question; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ClosedValidator is a dedicated + * validator for closed attribute. + */ +class ClosedValidator implements ValidatorInterface +{ + /** + * Validate an CLOSED attribute value + * + * @param mixed $value + * @param mixed $container A Question type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Question type + Util::subclassOf($container, Question::class, true); + + // Can be a boolean + if (is_bool($value)) { + return true; + } + + if (is_string($value)) { + // Can be a datetime + if (Util::validateDatetime($value)) { + return true; + } + + // Can be a URL + if (Util::validateUrl($value)) { + return true; + } + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // An Object or a Link + if (is_object($value)) { + return Util::validateLink($value) + || Util::validateObject($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ContentMapValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ContentMapValidator.php new file mode 100644 index 0000000000..e7493aa138 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ContentMapValidator.php @@ -0,0 +1,37 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ContentMapValidator is a dedicated + * validator for contentMap attribute. + */ +class ContentMapValidator extends ValidatorTools +{ + /** + * Validate a contentMap value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateMap('content', $value, $container); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ContentValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ContentValidator.php new file mode 100644 index 0000000000..b07c6f3e12 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ContentValidator.php @@ -0,0 +1,39 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ContentValidator is a dedicated + * validator for content attribute. + */ +class ContentValidator implements ValidatorInterface +{ + /** + * Validate a content attribute value + * + * @param mixed $value + * @param mixed $container + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Must be a string or null + if (is_null($value) || is_string($value)) { + return true; + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ContextValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ContextValidator.php new file mode 100644 index 0000000000..9cce11588f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ContextValidator.php @@ -0,0 +1,53 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ContextValidator is a dedicated + * validator for context attribute. + */ +class ContextValidator implements ValidatorInterface +{ + /** + * Validate a context attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // URL + if (Util::validateUrl($value)) { + return true; + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Object + if (is_object($value)) { + return Util::validateLink($value) + || Util::validateObject($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/CurrentValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/CurrentValidator.php new file mode 100644 index 0000000000..7a5facf617 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/CurrentValidator.php @@ -0,0 +1,49 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Collection; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\CurrentValidator is a dedicated + * validator for current attribute. + */ +class CurrentValidator implements ValidatorInterface +{ + /** + * Validate a current attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container must be a Collection + Util::subclassOf($container, Collection::class, true); + + // URL + if (Util::validateUrl($value)) { + return true; + } + + // Link or CollectionPage + return Util::validateLink($value) + || Util::validateCollectionPage($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/DeletedValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/DeletedValidator.php new file mode 100644 index 0000000000..c50fe5c6d4 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/DeletedValidator.php @@ -0,0 +1,49 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Tombstone; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\DeletedValidator is a dedicated + * validator for deleted attribute. + */ +class DeletedValidator implements ValidatorInterface +{ + /** + * Validate a DELETED attribute value + * + * @param mixed $value + * @param mixed $container A Tombstone type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Tombstone type + Util::subclassOf($container, Tombstone::class, true); + + if (is_string($value)) { + // MUST be a datetime + if (Util::validateDatetime($value)) { + return true; + } + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/DescribesValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/DescribesValidator.php new file mode 100644 index 0000000000..3feb3c64f9 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/DescribesValidator.php @@ -0,0 +1,48 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Profile; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\DescribesValidator is a dedicated + * validator for describes attribute. + */ +class DescribesValidator implements ValidatorInterface +{ + /** + * Validate an DESCRIBES attribute value + * + * @param mixed $value + * @param mixed $container A Profile type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Tombstone type + Util::subclassOf($container, Profile::class, true); + + if (is_object($value)) { + // MUST be an Object + return Util::subclassOf($value, ObjectType::class, true); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/DurationValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/DurationValidator.php new file mode 100644 index 0000000000..703b9f00fb --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/DurationValidator.php @@ -0,0 +1,47 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\DurationValidator is a dedicated + * validator for duration attribute. + */ +class DurationValidator implements ValidatorInterface +{ + /** + * Validate an DURATION attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container has an ObjectType type + Util::subclassOf($container, ObjectType::class, true); + + if (is_string($value)) { + // MUST be an XML 8601 Duration formatted string + return Util::isDuration($value, true); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/EndTimeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/EndTimeValidator.php new file mode 100644 index 0000000000..01a7a1d707 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/EndTimeValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\EndTimeValidator is a dedicated + * validator for endTime attribute. + */ +class EndTimeValidator implements ValidatorInterface +{ + /** + * Validate an ENDTIME attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container has an ObjectType type + Util::subclassOf($container, ObjectType::class, true); + + // MUST be a valid xsd:dateTime + return Util::validateDatetime($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/EndpointsValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/EndpointsValidator.php new file mode 100644 index 0000000000..2350bb0bb2 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/EndpointsValidator.php @@ -0,0 +1,78 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\EndpointsValidator is a dedicated + * validator for endpoints attribute. + */ +class EndpointsValidator implements ValidatorInterface +{ + /** + * Validate ENDPOINTS value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an AbstractActor type + Util::subclassOf($container, AbstractActor::class, true); + + // A link to a JSON-LD document + if (Util::validateUrl($value)) { + return true; + } + + // A map + return is_array($value) && $this->validateObject($value); + } + + /** + * Validate endpoints mapping + */ + protected function validateObject(array $item): bool + { + foreach ($item as $key => $value) { + switch ($key) { + case 'proxyUrl': + case 'oauthAuthorizationEndpoint': + case 'oauthTokenEndpoint': + case 'provideClientKey': + case 'signClientKey': + case 'sharedInbox': + if (!Util::validateUrl($value)) { + return false; + } + break; + // All other keys are not allowed + default: + return false; + } + + if (is_numeric($key)) { + return false; + } + } + + return true; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/FirstValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/FirstValidator.php new file mode 100644 index 0000000000..3965bdd46b --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/FirstValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\FirstValidator is a dedicated + * validator for first attribute. + */ +class FirstValidator extends CurrentValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/FollowersValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/FollowersValidator.php new file mode 100644 index 0000000000..e7ca4b41a4 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/FollowersValidator.php @@ -0,0 +1,72 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Collection; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollection; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\FollowersValidator is a dedicated + * validator for followers attribute. + */ +class FollowersValidator implements ValidatorInterface +{ + /** + * Validate a FOLLOWERS attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + * + * @todo Support indirect reference for followers attribute? + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an AbstractActor type + Util::subclassOf($container, AbstractActor::class, true); + + if (is_string($value)) { + return Util::validateUrl($value); + } + + // A collection + return is_object($value) && $this->validateObject($value); + } + + /** + * Validate that it is an OrderedCollection or a Collection + * + * @param object $collection + * + * @throws Exception + * @throws Exception + * + * @return bool + */ + protected function validateObject(object $collection): bool + { + return Util::subclassOf( + $collection, + OrderedCollection::class + ) || Util::subclassOf( + $collection, + Collection::class + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/FollowingValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/FollowingValidator.php new file mode 100644 index 0000000000..6602874db6 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/FollowingValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\FollowingValidator is a dedicated + * validator for followers attribute. + */ +class FollowingValidator extends FollowersValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/FormerTypeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/FormerTypeValidator.php new file mode 100644 index 0000000000..9aedeb871c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/FormerTypeValidator.php @@ -0,0 +1,47 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Tombstone; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\FormerTypeValidator is a dedicated + * validator for formerType attribute. + */ +class FormerTypeValidator implements ValidatorInterface +{ + /** + * Validate a formerType attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container has a Tombstone type + Util::subclassOf($container, Tombstone::class, true); + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // MUST be a valid Object type + return Util::isObjectType($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/GeneratorValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/GeneratorValidator.php new file mode 100644 index 0000000000..04292df45f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/GeneratorValidator.php @@ -0,0 +1,51 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\GeneratorValidator is a dedicated + * validator for generator attribute. + */ +class GeneratorValidator implements ValidatorInterface +{ + /** + * Validate a generator attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container has an ObjectType type + Util::subclassOf($container, ObjectType::class, true); + + if (Util::validateUrl($value)) { + return true; + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // MUST be a valid Actor type + return Util::isActorType($value) || Util::validateLink($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/HeightValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/HeightValidator.php new file mode 100644 index 0000000000..6a7cb4714c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/HeightValidator.php @@ -0,0 +1,44 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Image; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\HeightValidator is a dedicated + * validator for height attribute. + */ +class HeightValidator implements ValidatorInterface +{ + /** + * Validate height value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Link + Util::subclassOf($container, [Link::class, Image::class], true); + + // Must be a non-negative integer + return Util::validateNonNegativeInteger($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/HrefValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/HrefValidator.php new file mode 100644 index 0000000000..d2d9c0004a --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/HrefValidator.php @@ -0,0 +1,49 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\HrefValidator is a dedicated + * validator for href attribute. + */ +class HrefValidator implements ValidatorInterface +{ + /** + * Validate href value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Link or an Object + Util::subclassOf( + $container, + [Link::class, ObjectType::class], + true + ); + + // Must be a valid URL or a valid magnet link + return Util::validateUrl($value) + || Util::validateMagnet($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/HreflangValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/HreflangValidator.php new file mode 100644 index 0000000000..a9dade8ed7 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/HreflangValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\HreflangValidator is a dedicated + * validator for hreflang attribute. + */ +class HreflangValidator implements ValidatorInterface +{ + /** + * Validate href value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Link + Util::subclassOf($container, Link::class, true); + + // Must be a valid URL + return Util::validateBcp47($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/IconValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/IconValidator.php new file mode 100644 index 0000000000..a128e56ef1 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/IconValidator.php @@ -0,0 +1,87 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\IconValidator is a dedicated + * validator for icon attribute. + */ +class IconValidator implements ValidatorInterface +{ + /** + * Validate icon item + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + * + * @todo Implement size checks + * @todo Support Image objects and Link objects + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a ObjectType + Util::subclassOf($container, ObjectType::class, true); + + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + if (is_array($value)) { + foreach ($value as $item) { + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (is_string($item) && Util::validateUrl($item)) { + continue; + } + + if (!$this->validateObject($item)) { + return false; + } + } + + return true; + } + + // Must be an Image or a Link + return $this->validateObject($value); + } + + /** + * Validate an object format + * + * @param object $item + * + * @throws Exception + * + * @return bool + */ + protected function validateObject(object $item): bool + { + return Util::validateLink($item) + || Util::isType($item, 'Image'); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/IdValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/IdValidator.php new file mode 100644 index 0000000000..6449ca9379 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/IdValidator.php @@ -0,0 +1,36 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\IdValidator is a dedicated + * validator for id attribute. + */ +class IdValidator implements ValidatorInterface +{ + /** + * Validate an ID attribute value + * + * @param mixed $value + * @param mixed $container An object + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return Util::validateUrl($value) + || Util::validateOstatusTag($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ImageValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ImageValidator.php new file mode 100644 index 0000000000..b497b6766a --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ImageValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ImageValidator is a dedicated + * validator for image attribute. + */ +class ImageValidator extends IconValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/InReplyToValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/InReplyToValidator.php new file mode 100644 index 0000000000..d8999d28dd --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/InReplyToValidator.php @@ -0,0 +1,66 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\InReplyToValidator is a dedicated + * validator for inReplyTo attribute. + */ +class InReplyToValidator implements ValidatorInterface +{ + /** + * Validate inReplyTo value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is an ObjectType + Util::subclassOf( + $container, + ObjectType::class, + true + ); + + // null + if (is_null($value)) { + return true; + } + + // URL + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Object + if (is_object($value)) { + return Util::validateLink($value) + || Util::isObjectType($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/InboxValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/InboxValidator.php new file mode 100644 index 0000000000..5064880865 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/InboxValidator.php @@ -0,0 +1,71 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollection; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollectionPage; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\InboxValidator is a dedicated + * validator for inbox attribute. + */ +class InboxValidator implements ValidatorInterface +{ + /** + * Validate a inbox attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + * + * @todo Support indirect reference for followers attribute? + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an AbstractActor type + Util::subclassOf($container, AbstractActor::class, true); + + if (is_string($value)) { + return Util::validateUrl($value); + } + + // An OrderedCollection + return is_object($value) && $this->validateObject($value); + } + + /** + * Validate that it is an OrderedCollection + * + * @param object $collection + * + * @throws Exception + * + * @return bool + */ + protected function validateObject(object $collection): bool + { + return Util::subclassOf( + $collection, + OrderedCollection::class + ) || Util::subclassOf( + $collection, + OrderedCollectionPage::class + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/InstrumentValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/InstrumentValidator.php new file mode 100644 index 0000000000..1e19a4db0c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/InstrumentValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\InstrumentValidator is a dedicated + * validator for instrument attribute. + */ +class InstrumentValidator extends ActorValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ItemsValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ItemsValidator.php new file mode 100644 index 0000000000..e6a3831457 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ItemsValidator.php @@ -0,0 +1,77 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Collection; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ItemsValidator is a dedicated + * validator for items attribute. + */ +class ItemsValidator extends ValidatorTools +{ + /** + * Validate items value + * + * @param mixed $value + * @param mixed $container A Collection type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Collection + Util::subclassOf( + $container, + [Collection::class], + true + ); + + // URL type + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + // Empty array + if (!count($value)) { + return true; + } + $value = Util::arrayToType($value); + } + + // Link type + if (is_object($value)) { + return Util::subclassOf($value, Link::class, true); + } + + // A Collection + if (!is_array($value)) { + return false; + } + + if (!count($value)) { + return false; + } + + return $this->validateObjectCollection( + $value, + $this->getCollectionItemsValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/LastValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/LastValidator.php new file mode 100644 index 0000000000..8916ae1cd7 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/LastValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\LastValidator is a dedicated + * validator for last attribute. + */ +class LastValidator extends CurrentValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/LatitudeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/LatitudeValidator.php new file mode 100644 index 0000000000..efa2aadd63 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/LatitudeValidator.php @@ -0,0 +1,42 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Place; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\LatitudeValidator is a dedicated + * validator for latitude attribute. + */ +class LatitudeValidator implements ValidatorInterface +{ + /** + * Validate a latitude attribute value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Place + Util::subclassOf($container, Place::class, true); + + return Util::between($value, -90, 90); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/LikedValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/LikedValidator.php new file mode 100644 index 0000000000..c59f456f38 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/LikedValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\LikedValidator is a dedicated + * validator for liked attribute. + */ +class LikedValidator extends FollowersValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/LocationValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/LocationValidator.php new file mode 100644 index 0000000000..1c614ca20e --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/LocationValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\LocationValidator is a dedicated + * validator for location attribute. + */ +class LocationValidator extends InReplyToValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/LongitudeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/LongitudeValidator.php new file mode 100644 index 0000000000..8373c95dd0 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/LongitudeValidator.php @@ -0,0 +1,42 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Place; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\LongitudeValidator is a dedicated + * validator for longitude attribute. + */ +class LongitudeValidator implements ValidatorInterface +{ + /** + * Validate a longitude value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Place + Util::subclassOf($container, Place::class, true); + + return Util::between($value, -180, 180); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/MediaTypeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/MediaTypeValidator.php new file mode 100644 index 0000000000..4c2915d22c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/MediaTypeValidator.php @@ -0,0 +1,36 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\MediaTypeValidator is a dedicated + * validator for mediaType attribute. + */ +class MediaTypeValidator implements ValidatorInterface +{ + /** + * Validate a mediaType attribute value + * + * @param mixed $value + * @param mixed $container + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return is_null($value) + || Util::validateMediaType($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/NameMapValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/NameMapValidator.php new file mode 100644 index 0000000000..7fc1051573 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/NameMapValidator.php @@ -0,0 +1,37 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\NameMapValidator is a dedicated + * validator for nameMap attribute. + */ +class NameMapValidator extends ValidatorTools +{ + /** + * Validate a nameMap value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateMap('name', $value, $container); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/NameValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/NameValidator.php new file mode 100644 index 0000000000..73553fcb2d --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/NameValidator.php @@ -0,0 +1,39 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\NameValidator is a dedicated + * validator for name attribute. + */ +class NameValidator implements ValidatorInterface +{ + /** + * Validate a name attribute value + * + * @param mixed $value + * @param mixed $container + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + if (is_null($value) || $value === '') { + return true; + } + + return Util::validatePlainText($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/NextValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/NextValidator.php new file mode 100644 index 0000000000..feb0384493 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/NextValidator.php @@ -0,0 +1,62 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\CollectionPage; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollectionPage; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\NextValidator is a dedicated + * validator for next attribute. + */ +class NextValidator implements ValidatorInterface +{ + /** + * Validate a next value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is CollectionPage or OrderedCollectionPage type + Util::subclassOf( + $container, + [CollectionPage::class, OrderedCollectionPage::class], + true + ); + + // URL + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Collection + if (is_object($value)) { + return Util::validateLink($value) + || Util::validateCollectionPage($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ObjectValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ObjectValidator.php new file mode 100644 index 0000000000..7996ebdc4e --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ObjectValidator.php @@ -0,0 +1,85 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ObjectValidator is a dedicated + * validator for object attribute. + */ +class ObjectValidator implements ValidatorInterface +{ + /** + * Validate an object value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is an ObjectType or a Link + Util::subclassOf( + $container, + [Activity::class], + true + ); + + // URL + if (is_string($value)) { + return Util::validateUrl($value) + || Util::validateOstatusTag($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Object + if (is_object($value)) { + return Util::validateLink($value) + || Util::isObjectType($value); + } + + // Collection + if (is_array($value)) { + foreach ($value as $item) { + if (is_string($item) && Util::validateUrl($item)) { + continue; + } + + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (is_object($item) + && Util::subclassOf($item, [ObjectType::class], true)) { + continue; + } + + return false; + } + + return count($value) > 0; + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/OneOfValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/OneOfValidator.php new file mode 100644 index 0000000000..eca9b01528 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/OneOfValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\OneOfValidator is a dedicated + * validator for oneOf attribute. + */ +class OneOfValidator extends AnyOfValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/OrderedItemsValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/OrderedItemsValidator.php new file mode 100644 index 0000000000..857bbd5042 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/OrderedItemsValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\OrderedItemsValidator is a dedicated + * validator for orderedItems attribute. + */ +class OrderedItemsValidator extends ItemsValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/OriginValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/OriginValidator.php new file mode 100644 index 0000000000..a146a6103d --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/OriginValidator.php @@ -0,0 +1,61 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Activity; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\OriginValidator is a dedicated + * validator for origin attribute. + */ +class OriginValidator implements ValidatorInterface +{ + /** + * Validate an origin value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is an Activity + Util::subclassOf( + $container, + [Activity::class], + true + ); + + // URL + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Object + if (is_object($value)) { + return Util::validateLink($value) + || Util::isObjectType($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/OutboxValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/OutboxValidator.php new file mode 100644 index 0000000000..8e2663c040 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/OutboxValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\OutboxValidator is a dedicated + * validator for outbox attribute. + */ +class OutboxValidator extends InboxValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/PartOfValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/PartOfValidator.php new file mode 100644 index 0000000000..b59cc9d766 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/PartOfValidator.php @@ -0,0 +1,62 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\CollectionPage; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollectionPage; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\PartOfValidator is a dedicated + * validator for partOf attribute. + */ +class PartOfValidator implements ValidatorInterface +{ + /** + * Validate a partOf value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is CollectionPage or OrderedCollectionPage type + Util::subclassOf( + $container, [ + CollectionPage::class, OrderedCollectionPage::class, + ], true + ); + + // URL + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Collection + if (is_object($value)) { + return Util::validateLink($value) + || Util::validateCollection($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/PreferredUsernameValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/PreferredUsernameValidator.php new file mode 100644 index 0000000000..a9911e3d7f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/PreferredUsernameValidator.php @@ -0,0 +1,44 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\PreferredUsernameValidator is a dedicated + * validator for preferredUsername attribute. + */ +class PreferredUsernameValidator extends ValidatorTools +{ + /** + * Validate preferredUsername value + * + * @param mixed $value + * @param mixed $container An Actor + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an Actor + Util::subclassOf($container, AbstractActor::class, true); + + return $this->validateString( + $value + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/PrevValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/PrevValidator.php new file mode 100644 index 0000000000..638ab99858 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/PrevValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\PrevValidator is a dedicated + * validator for prev attribute. + */ +class PrevValidator extends NextValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/PreviewValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/PreviewValidator.php new file mode 100644 index 0000000000..fa4a5bef8c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/PreviewValidator.php @@ -0,0 +1,62 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\PreviewValidator is a dedicated + * validator for preview attribute. + */ +class PreviewValidator implements ValidatorInterface +{ + /** + * Validate a preview value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is an ObjectType or a Link + Util::subclassOf( + $container, + [ObjectType::class, Link::class], + true + ); + + // URL + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Object + if (is_object($value)) { + return Util::validateLink($value) + || Util::isObjectType($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/PublishedValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/PublishedValidator.php new file mode 100644 index 0000000000..5753126e8c --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/PublishedValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\PublishedValidator is a dedicated + * validator for published attribute. + */ +class PublishedValidator extends EndTimeValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/RadiusValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/RadiusValidator.php new file mode 100644 index 0000000000..76b1bfbfd5 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/RadiusValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Place; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\RadiusValidator is a dedicated + * validator for radius attribute. + */ +class RadiusValidator implements ValidatorInterface +{ + /** + * Validate radius value + * + * @param mixed $value + * @param mixed $container A Place + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container must be Place + Util::subclassOf($container, Place::class, true); + + // Must be a valid radius + return Util::validateNonNegativeNumber($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/RelValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/RelValidator.php new file mode 100644 index 0000000000..dac252c984 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/RelValidator.php @@ -0,0 +1,54 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\RelValidator is a dedicated + * validator for rel attribute. + */ +class RelValidator implements ValidatorInterface +{ + /** + * Validate rel value + * + * @param mixed $value + * @param mixed $container A Link + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is a Link + Util::subclassOf($container, Link::class, true); + + // Must be a valid Rel + if (is_array($value)) { + foreach ($value as $key => $item) { + if (!is_int($key) + || !Util::validateRel($item)) { + return false; + } + } + + return true; + } + + return Util::validateRel($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/RepliesValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/RepliesValidator.php new file mode 100644 index 0000000000..6997406b89 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/RepliesValidator.php @@ -0,0 +1,61 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\RepliesValidator is a dedicated + * validator for replies attribute. + */ +class RepliesValidator implements ValidatorInterface +{ + /** + * Validate replies value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is an ObjectType + Util::subclassOf( + $container, + ObjectType::class, + true + ); + + // URL + if (is_string($value)) { + return Util::validateUrl($value); + } + + if (is_array($value)) { + $value = Util::arrayToType($value); + } + + // Link or Collection + if (is_object($value)) { + return Util::validateLink($value) + || Util::validateCollection($value); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ResultValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ResultValidator.php new file mode 100644 index 0000000000..3dabac6404 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ResultValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ResultValidator is a dedicated + * validator for result attribute. + */ +class ResultValidator extends OriginValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/SourceValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/SourceValidator.php new file mode 100644 index 0000000000..260ecbcf67 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/SourceValidator.php @@ -0,0 +1,58 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\SourceValidator is a dedicated + * validator for source attribute. + */ +class SourceValidator implements ValidatorInterface +{ + /** + * Validate source value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container is an ObjectType + Util::subclassOf( + $container, + ObjectType::class, + true + ); + + if (is_array($value)) { + $value = (object) $value; + } + + if (is_object($value)) { + return Util::hasProperties( + $value, + ['content', 'mediaType'], + true + ); + } + + return false; + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/StartIndexValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/StartIndexValidator.php new file mode 100644 index 0000000000..da4647ace1 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/StartIndexValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\OrderedCollectionPage; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\StartIndexValidator is a dedicated + * validator for startIndex attribute. + */ +class StartIndexValidator implements ValidatorInterface +{ + /** + * Validate startIndex value + * + * @param mixed $value + * @param mixed $container An OrderedCollectionPage + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container type is OrderedCollectionPage + Util::subclassOf($container, OrderedCollectionPage::class, true); + + // Must be a non-negative integer + return Util::validateNonNegativeInteger($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/StartTimeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/StartTimeValidator.php new file mode 100644 index 0000000000..1e539b3f37 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/StartTimeValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\StartTimeValidator is a dedicated + * validator for startTime attribute. + */ +class StartTimeValidator extends EndTimeValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/StreamsValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/StreamsValidator.php new file mode 100644 index 0000000000..7c483e5f6a --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/StreamsValidator.php @@ -0,0 +1,44 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\StreamsValidator is a dedicated + * validator for streams attribute. + */ +class StreamsValidator implements ValidatorInterface +{ + /** + * Validate streams value + * + * @param mixed $value + * @param mixed $container An object + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an Actor + Util::subclassOf($container, AbstractActor::class, true); + + // Must be an array + // @todo Better validation should be done + return is_array($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/SummaryMapValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/SummaryMapValidator.php new file mode 100644 index 0000000000..9e93909c7a --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/SummaryMapValidator.php @@ -0,0 +1,37 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\SummaryMapValidator is a dedicated + * validator for summaryMap attribute. + */ +class SummaryMapValidator extends ValidatorTools +{ + /** + * Validate a summaryMap attribute value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + return $this->validateMap('summary', $value, $container); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/SummaryValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/SummaryValidator.php new file mode 100644 index 0000000000..e1688e0229 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/SummaryValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\SummaryValidator is a dedicated + * validator for summary attribute. + */ +class SummaryValidator implements ValidatorInterface +{ + /** + * Validate a summary attribute value + * + * @param mixed $value + * @param mixed $container + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an ObjectType type + Util::subclassOf($container, ObjectType::class, true); + + // Must be a string + return is_null($value) || is_string($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/TagValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/TagValidator.php new file mode 100644 index 0000000000..d44b6642f5 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/TagValidator.php @@ -0,0 +1,41 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\TagValidator is a dedicated + * validator for tag attribute. + */ +class TagValidator extends ValidatorTools +{ + /** + * Validate a tag value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + if (!count($value)) { + return true; + } + + return $this->validateObjectCollection( + $value, + $this->getCollectionItemsValidator() + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/TargetValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/TargetValidator.php new file mode 100644 index 0000000000..8d5891c0c5 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/TargetValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\TargetValidator is a dedicated + * validator for target attribute. + */ +class TargetValidator extends ActorValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/ToValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/ToValidator.php new file mode 100644 index 0000000000..9f6b13ccd5 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/ToValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\ToValidator is a dedicated + * validator for to attribute. + */ +class ToValidator extends BtoValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/TotalItemsValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/TotalItemsValidator.php new file mode 100644 index 0000000000..3edc306e5f --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/TotalItemsValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Collection; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\TotalItemsValidator is a dedicated + * validator for totalItems attribute. + */ +class TotalItemsValidator implements ValidatorInterface +{ + /** + * Validate totalItems value + * + * @param mixed $value + * @param mixed $container A Collection + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container type is Collection + Util::subclassOf($container, Collection::class, true); + + // Must be a non-negative integer + return Util::validateNonNegativeInteger($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/TypeValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/TypeValidator.php new file mode 100644 index 0000000000..da375e8701 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/TypeValidator.php @@ -0,0 +1,49 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\TypeValidator is a dedicated + * validator for type attribute. + */ +class TypeValidator extends ValidatorTools +{ + /** + * Validate a type value + * + * @param mixed $value + * @param mixed $container An Object type + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an ObjectType or a Link + Util::subclassOf( + $container, + [ObjectType::class, Link::class], + true + ); + + return $this->validateString( + $value + ); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/UnitsValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/UnitsValidator.php new file mode 100644 index 0000000000..7e051fa800 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/UnitsValidator.php @@ -0,0 +1,43 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\Object\Place; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\UnitsValidator is a dedicated + * validator for units attribute. + */ +class UnitsValidator implements ValidatorInterface +{ + /** + * Validate units value + * + * @param mixed $value + * @param mixed $container A Place + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Container must be Place + Util::subclassOf($container, Place::class, true); + + // Must be a valid units + return Util::validateUnits($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/UpdatedValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/UpdatedValidator.php new file mode 100644 index 0000000000..564f1deb57 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/UpdatedValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\UpdatedValidator is a dedicated + * validator for updated attribute. + */ +class UpdatedValidator extends EndTimeValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/UrlValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/UrlValidator.php new file mode 100644 index 0000000000..71be415e68 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/UrlValidator.php @@ -0,0 +1,70 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\Link; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Util; +use Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\UrlValidator is a dedicated + * validator for url attribute. + */ +class UrlValidator implements ValidatorInterface +{ + /** + * Validate url value + * + * @param mixed $value + * @param mixed $container A Link + * + * @throws Exception + * + * @return bool + */ + public function validate(mixed $value, mixed $container): bool + { + // Validate that container is an ObjectType + Util::subclassOf($container, ObjectType::class, true); + + // Must be a valid URL + if (is_array($value) && is_int(key($value))) { + foreach ($value as $key => $item) { + if (!$this->validateUrlOrLink($item)) { + return false; + } + } + + return true; + } + + return $this->validateUrlOrLink($value); + } + + /** + * Validate that a value is a Link or a URL + * + * @param Link|string $value + * + * @throws Exception + * + * @return bool + */ + protected function validateUrlOrLink(Link|string $value): bool + { + return Util::validateUrl($value) + || Util::validateLink($value) + || Util::validateMagnet($value); + } +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/Validator/WidthValidator.php b/plugins/ActivityStreamsTwo/Util/Type/Validator/WidthValidator.php new file mode 100644 index 0000000000..90a8a19b6a --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/Validator/WidthValidator.php @@ -0,0 +1,20 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type\Validator; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\Validator\WidthValidator is a dedicated + * validator for width attribute. + */ +class WidthValidator extends HeightValidator +{ +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/ValidatorInterface.php b/plugins/ActivityStreamsTwo/Util/Type/ValidatorInterface.php new file mode 100644 index 0000000000..c0c36db63e --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/ValidatorInterface.php @@ -0,0 +1,21 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface specifies methods that must be + * implemented for attribute (property) validation. + */ +interface ValidatorInterface +{ + public function validate(mixed $value, mixed $container): bool; +} diff --git a/plugins/ActivityStreamsTwo/Util/Type/ValidatorTools.php b/plugins/ActivityStreamsTwo/Util/Type/ValidatorTools.php new file mode 100644 index 0000000000..17371fa392 --- /dev/null +++ b/plugins/ActivityStreamsTwo/Util/Type/ValidatorTools.php @@ -0,0 +1,299 @@ +. + */ + +namespace Plugin\ActivityStreamsTwo\Util\Type; + +use Exception; +use Plugin\ActivityStreamsTwo\Util\Type\Core\ObjectType; +use Plugin\ActivityStreamsTwo\Util\Type\Extended\AbstractActor; + +/** + * \Plugin\ActivityStreamsTwo\Util\Type\ValidatorTools is an abstract class for + * attribute validation. + * Its purpose is to be extended by Plugin\ActivityStreamsTwo\Util\Type\Validator\* + * classes. + * It provides some methods to make some regular validations. + * It implements \Plugin\ActivityStreamsTwo\Util\Type\ValidatorInterface. + */ +abstract class ValidatorTools implements ValidatorInterface +{ + /** + * Validate a map attribute value. + * + * @param string $type An attribute name + * @param mixed $map + * @param object $container A valid container + * + * @throws Exception + * + * @return bool + */ + protected function validateMap(string $type, mixed $map, object $container): bool + { + // A map + if (!is_array($map)) { + return false; + } + + foreach ($map as $key => $value) { + if (!Util::validateBcp47($key) + || !Validator::validate($type, $value, $container) + ) { + return false; + } + } + + return true; + } + + /** + * Validate an attribute value + * + * @param mixed $value + * @param mixed $container An object + * @param callable $callback A dedicated validator + * + * @throws Exception + * + * @return bool + */ + public function validateListOrObject(mixed $value, mixed $container, callable $callback): bool + { + Util::subclassOf($container, ObjectType::class, true); + + // Not supported: Can be a JSON string + // Must be a value like a URL, a text + if (is_string($value)) { + return $callback($value); + } + + if (is_array($value)) { + // Can be empty + if (!count($value)) { + return true; + } + + // A collection + if (is_int(key($value))) { + return $this->validateObjectCollection($value, $callback); + } + + $value = Util::arrayToType($value); + } + + if (!is_object($value)) { + return false; + } + + return $callback($value); + } + + /** + * Validate a list of Collection + * + * @param array $collection + * @param callable $callback A dedicated validator + * + * @return bool + */ + protected function validateObjectCollection(array $collection, callable $callback): bool + { + foreach ($collection as $item) { + if ($callback($item)) { + continue; + } + + return false; + } + + return true; + } + + /** + * Validate that a value is a string + * + * @param string $value + * + * @throws Exception + * + * @return bool + */ + protected function validateString(string $value): bool + { + if (!is_string($value) || strlen($value) < 1) { + throw new Exception( + sprintf( + 'Value must be a non-empty string. Given: "%s"', + print_r($value, true) + ) + ); + } + + return true; + } + + /** + * A callback function for validateListOrObject method + * + * It validates a Link or a named object + */ + protected function getLinkOrNamedObjectValidator(): callable + { + return static function ($item): bool { + if (is_string($item)) { + return Util::validateUrl($item); + } + + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (is_object($item)) { + Util::hasProperties($item, ['type'], true); + + // Validate Link type + if ($item->type === 'Link') { + return Util::validateLink($item); + } + + // Validate Object type + Util::hasProperties($item, ['name'], true); + + return is_string($item->name); + } + + return false; + }; + } + + /** + * A callback function for validateListOrObject method + * + * Validate a reference with a Link or an Object with a URL + */ + protected function getLinkOrUrlObjectValidator(): callable + { + return static function ($item): bool { + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (is_object($item) + && Util::isLinkOrUrlObject($item)) { + return true; + } + + if (Util::validateUrl($item)) { + return true; + } + + return false; + }; + } + + /** + * A callback function for attachment validation + * + * Validate a reference with a Link, an Object with a URL + * or an ObjectType + */ + protected function getAttachmentValidator(): callable + { + return static function ($item): bool { + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (is_object($item)) { + if (Util::isLinkOrUrlObject($item)) { + return true; + } + + return $item instanceof ObjectType; + } + + if (Util::validateUrl($item)) { + return true; + } + + return false; + }; + } + + /** + * Validate that a Question answer is a Note + */ + protected function getQuestionAnswerValidator(): callable + { + return static function ($item): bool { + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (!is_object($item)) { + return false; + } + + Util::hasProperties($item, ['type', 'name'], true); + + return $item->type === 'Note' + && is_scalar($item->name); + }; + } + + /** + * Validate that a list of items is valid + */ + protected function getCollectionItemsValidator(): callable + { + return static function ($item): bool { + if (is_string($item)) { + return Util::validateUrl($item); + } + + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (!is_object($item)) { + return false; + } + + return Util::hasProperties($item, ['type'], true); + }; + } + + /** + * Validate that a list of items are actors + */ + protected function getCollectionActorsValidator(): callable + { + return static function ($item): bool { + if (is_string($item)) { + return Util::validateUrl($item); + } + + if (is_array($item)) { + $item = Util::arrayToType($item); + } + + if (!is_object($item)) { + return false; + } + // id must be filled + if ($item instanceof AbstractActor) { + return !is_null($item->id); + } + + return Util::validateLink($item); + }; + } +}