2020-03-29 20:56:35 +01:00
< ? php
2021-11-28 13:09:04 +00:00
declare ( strict_types = 1 );
2021-10-28 17:34:01 +01:00
2020-03-29 20:56:35 +01:00
// {{{ License
2020-09-05 03:34:01 +01:00
2020-05-20 17:53:53 +01:00
// This file is part of GNU social - https://www.gnu.org/software/social
2020-03-29 20:56:35 +01:00
//
// GNU social is free software: you can redistribute it and/or modify
2020-05-10 21:43:15 +01:00
// it under the terms of the GNU Affero General Public License as published by
2020-03-29 20:56:35 +01:00
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU social is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
2020-05-10 21:43:15 +01:00
// You should have received a copy of the GNU Affero General Public License
2020-03-29 20:56:35 +01:00
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
2020-09-05 03:34:01 +01:00
2020-03-29 20:56:35 +01:00
// }}}
namespace App\Entity ;
2020-08-15 08:03:58 +01:00
use App\Core\Cache ;
2020-07-25 18:53:37 +01:00
use App\Core\DB\DB ;
2020-08-08 17:10:25 +01:00
use App\Core\Entity ;
2021-11-27 15:06:46 +00:00
use App\Core\Event ;
2021-09-14 13:40:50 +01:00
use App\Core\Router\Router ;
2020-07-22 12:40:53 +01:00
use App\Core\UserRoles ;
2021-09-14 13:40:50 +01:00
use App\Util\Exception\NicknameException ;
2021-11-16 23:24:06 +00:00
use App\Util\Exception\NotFoundException ;
2021-09-14 13:40:50 +01:00
use App\Util\Nickname ;
2021-09-18 04:54:35 +01:00
use Component\Avatar\Avatar ;
2021-11-28 13:09:04 +00:00
use Component\Tag\Tag as TagComponent ;
2020-05-10 21:43:15 +01:00
use DateTimeInterface ;
2020-07-25 18:53:37 +01:00
use Functional as F ;
2020-05-10 21:43:15 +01:00
2020-03-29 20:56:35 +01:00
/**
2020-08-13 00:57:22 +01:00
* Entity for actors
2020-03-29 20:56:35 +01:00
*
* @ category DB
* @ package GNUsocial
*
* @ author Zach Copley < zach @ status . net >
* @ copyright 2010 StatusNet Inc .
* @ author Mikael Nordfeldth < mmn @ hethane . se >
* @ copyright 2009 - 2014 Free Software Foundation , Inc http :// www . fsf . org
2021-02-19 23:29:43 +00:00
* @ author Hugo Sales < hugo @ hsal . es >
* @ copyright 2020 - 2021 Free Software Foundation , Inc http :// www . fsf . org
2020-03-29 20:56:35 +01:00
* @ license https :// www . gnu . org / licenses / agpl . html GNU AGPL v3 or later
*/
2021-09-18 03:22:27 +01:00
class Actor extends Entity
2020-03-29 20:56:35 +01:00
{
2020-03-30 15:00:13 +01:00
// {{{ Autocode
2021-05-05 17:03:03 +01:00
// @codeCoverageIgnoreStart
2020-03-30 16:13:51 +01:00
private int $id ;
private string $nickname ;
2021-10-29 22:05:10 +01:00
private ? string $fullname = null ;
2021-11-28 13:09:04 +00:00
private int $roles = 4 ;
2021-12-11 22:19:37 +00:00
private int $type ;
2021-12-20 16:25:10 +00:00
private ? string $homepage = null ;
private ? string $bio = null ;
private ? string $location = null ;
2020-03-30 16:13:51 +01:00
private ? float $lat ;
private ? float $lon ;
private ? int $location_id ;
2020-06-30 19:20:50 +01:00
private ? int $location_service ;
2021-11-16 23:24:06 +00:00
private bool $is_local ;
2021-10-28 17:34:01 +01:00
private DateTimeInterface $created ;
private DateTimeInterface $modified ;
2020-03-30 16:13:51 +01:00
public function setId ( int $id ) : self
{
$this -> id = $id ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getId () : int
{
return $this -> id ;
}
public function setNickname ( string $nickname ) : self
{
$this -> nickname = $nickname ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getNickname () : string
{
return $this -> nickname ;
}
2021-11-27 04:11:35 +00:00
public function setFullname ( ? string $fullname ) : self
2020-03-30 16:13:51 +01:00
{
$this -> fullname = $fullname ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2021-10-29 22:05:10 +01:00
public function getFullname () : ? string
2020-03-30 16:13:51 +01:00
{
2021-11-28 13:09:04 +00:00
if ( \is_null ( $this -> fullname )) {
2021-10-29 22:05:10 +01:00
return null ;
}
2020-03-30 16:13:51 +01:00
return $this -> fullname ;
}
2020-07-25 03:03:16 +01:00
public function setRoles ( int $roles ) : self
2020-07-22 12:40:53 +01:00
{
$this -> roles = $roles ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-07-25 03:03:16 +01:00
public function getRoles () : int
2020-07-22 12:40:53 +01:00
{
return $this -> roles ;
}
2021-12-11 22:19:37 +00:00
public function setType ( int $type ) : self
{
$this -> type = $type ;
return $this ;
}
public function getType () : int
{
return $this -> type ;
}
2020-03-30 16:13:51 +01:00
public function setHomepage ( ? string $homepage ) : self
{
$this -> homepage = $homepage ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getHomepage () : ? string
{
return $this -> homepage ;
}
public function setBio ( ? string $bio ) : self
{
$this -> bio = $bio ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getBio () : ? string
{
return $this -> bio ;
}
public function setLocation ( ? string $location ) : self
{
$this -> location = $location ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getLocation () : ? string
{
return $this -> location ;
}
public function setLat ( ? float $lat ) : self
{
$this -> lat = $lat ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getLat () : ? float
{
return $this -> lat ;
}
public function setLon ( ? float $lon ) : self
{
$this -> lon = $lon ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getLon () : ? float
{
return $this -> lon ;
}
public function setLocationId ( ? int $location_id ) : self
{
$this -> location_id = $location_id ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-03-30 16:13:51 +01:00
public function getLocationId () : ? int
{
return $this -> location_id ;
}
2020-06-30 19:20:50 +01:00
public function setLocationService ( ? int $location_service ) : self
2020-03-30 16:13:51 +01:00
{
2020-06-30 19:20:50 +01:00
$this -> location_service = $location_service ;
2020-03-30 16:13:51 +01:00
return $this ;
}
2020-08-08 17:10:25 +01:00
2020-06-30 19:20:50 +01:00
public function getLocationService () : ? int
2020-03-30 16:13:51 +01:00
{
2020-06-30 19:20:50 +01:00
return $this -> location_service ;
2020-03-30 16:13:51 +01:00
}
2021-11-16 23:24:06 +00:00
public function setIsLocal ( bool $is_local ) : self
{
$this -> is_local = $is_local ;
return $this ;
}
public function getIsLocal () : bool
{
return $this -> is_local ;
}
2021-05-05 13:19:10 +01:00
public function setCreated ( DateTimeInterface $created ) : self
2020-03-30 16:13:51 +01:00
{
$this -> created = $created ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2021-05-05 13:19:10 +01:00
public function getCreated () : DateTimeInterface
2020-03-30 16:13:51 +01:00
{
return $this -> created ;
}
2021-05-05 13:19:10 +01:00
public function setModified ( DateTimeInterface $modified ) : self
2020-03-30 16:13:51 +01:00
{
$this -> modified = $modified ;
return $this ;
}
2020-08-08 17:10:25 +01:00
2021-05-05 13:19:10 +01:00
public function getModified () : DateTimeInterface
2020-03-30 16:13:51 +01:00
{
return $this -> modified ;
}
2021-05-05 17:03:03 +01:00
// @codeCoverageIgnoreEnd
2020-03-30 15:00:13 +01:00
// }}} Autocode
2020-03-29 20:56:35 +01:00
2021-12-11 22:19:37 +00:00
public const PERSON = 1 ;
public const GROUP = 2 ;
public const ORGANIZATION = 3 ;
public const BUSINESS = 4 ;
public const BOT = 5 ;
2021-12-09 21:59:49 +00:00
public static function cacheKeys ( int $actor_id , mixed $other = null ) : array
{
return [
'id' => " actor-id- { $actor_id } " ,
'nickname' => " actor-nickname-id- { $actor_id } " ,
'fullname' => " actor-fullname-id- { $actor_id } " ,
'tags' => \is_null ( $other ) ? " actor-circles-and-tags- { $actor_id } " : " actor-circles-and-tags- { $actor_id } -by- { $other } " , // $other is $context_id
'subscriber' => " subscriber- { $actor_id } " ,
'subscribed' => " subscribed- { $actor_id } " ,
'relative-nickname' => " actor- { $actor_id } -relative-nickname- { $other } " , // $other is $nickname
];
}
2021-09-14 17:15:37 +01:00
public function getLocalUser ()
{
2021-11-16 23:24:06 +00:00
if ( $this -> getIsLocal ()) {
return DB :: findOneBy ( 'local_user' , [ 'id' => $this -> getId ()]);
} else {
throw new NotFoundException ( 'This is a remote actor.' );
}
2021-09-14 17:15:37 +01:00
}
2021-11-27 04:12:44 +00:00
public function isGroup ()
{
// TODO: implement
return false ;
}
2021-09-18 04:54:35 +01:00
public function getAvatarUrl ( string $size = 'full' )
2020-11-29 04:55:23 +00:00
{
2021-12-04 11:56:27 +00:00
return Avatar :: getUrl ( $this -> getId (), $size );
2020-11-29 04:55:23 +00:00
}
2021-12-02 15:36:08 +00:00
public function getAvatarDimensions ( string $size = 'full' )
{
return Avatar :: getDimensions ( $this -> getId (), $size );
}
2021-10-04 17:00:58 +01:00
public static function getById ( int $id ) : ? self
2020-07-25 03:03:16 +01:00
{
2021-12-09 21:59:49 +00:00
return Cache :: get ( self :: cacheKeys ( $id )[ 'id' ], fn () => DB :: find ( 'actor' , [ 'id' => $id ]));
2020-08-08 17:10:25 +01:00
}
2020-07-25 03:03:16 +01:00
2021-10-04 17:00:58 +01:00
public static function getNicknameById ( int $id ) : string
2020-08-08 17:10:25 +01:00
{
2021-12-09 21:59:49 +00:00
return Cache :: get ( self :: cacheKeys ( $id )[ 'nickname' ], fn () => self :: getById ( $id ) -> getNickname ());
2020-08-08 17:10:25 +01:00
}
2021-10-29 22:05:10 +01:00
public static function getFullnameById ( int $id ) : ? string
2021-10-26 14:47:28 +01:00
{
2021-12-09 21:59:49 +00:00
return Cache :: get ( self :: cacheKeys ( $id )[ 'fullname' ], fn () => self :: getById ( $id ) -> getFullname ());
2021-10-26 14:47:28 +01:00
}
2021-12-05 17:50:15 +00:00
/**
* For consistency with Note
*/
public function getActorId () : int
{
return $this -> getId ();
}
2021-11-27 04:11:35 +00:00
/**
2021-11-29 15:31:02 +00:00
* Tags attributed to self , shortcut function for increased legibility
2021-11-27 04:11:35 +00:00
*
2021-12-01 12:07:43 +00:00
* @ return array < int , array > [ ActorCircle [], ActorTag []] resulting lists
2021-11-27 04:11:35 +00:00
*/
2021-08-04 21:06:58 +01:00
public function getSelfTags ( bool $_test_force_recompute = false ) : array
2020-08-08 17:10:25 +01:00
{
2021-12-09 21:59:49 +00:00
return $this -> getOtherTags ( context : $this -> getId (), _test_force_recompute : $_test_force_recompute );
2021-11-27 04:11:35 +00:00
}
/**
* Get tags that other people put on this actor , in reverse - chron order
*
2021-12-09 21:59:49 +00:00
* @ param null | Actor | int $context Actor we are requesting as :
* - If null = All tags attributed to self by other actors ( excludes self tags )
* - If self = Same as getSelfTags
* - otherwise = Tags that $context attributed to $this
* @ param null | int $offset Offset from latest
* @ param null | int $limit Max number to get
2021-11-28 13:09:04 +00:00
*
2021-12-01 12:07:43 +00:00
* @ return array < int , array > [ ActorCircle [], ActorTag []] resulting lists
2021-11-27 04:11:35 +00:00
*/
2021-12-09 21:59:49 +00:00
public function getOtherTags ( self | int | null $context = null , ? int $offset = null , ? int $limit = null , bool $_test_force_recompute = false ) : array
2021-11-27 04:11:35 +00:00
{
2021-12-09 21:59:49 +00:00
if ( \is_null ( $context )) {
2021-11-27 04:11:35 +00:00
return Cache :: get (
2021-12-09 21:59:49 +00:00
self :: cacheKeys ( $this -> getId ())[ 'tags' ],
[CORE][DB][ENTITY][Actor] Make DB::dql return a chunked array if selecting multiple entities, remove partitioning from callsite
`DB::dql('select a, b, from a join b')` would previously return `[a,
b, a, b, ...]` (or even `[b, a, b, a, ...]`), and now will return
`[[a, a, ...], [b, b, ...]]`. The issue would be further compounded
when selecting even more entities, where the order would be
unpredictable
2021-12-01 00:42:56 +00:00
fn () => DB :: dql (
<<< 'EOQ'
SELECT circle , tag
FROM actor_tag tag
JOIN actor_circle circle
WITH tag . tagger = circle . tagger
AND tag . tag = circle . tag
WHERE tag . tagged = : id
ORDER BY tag . modified DESC , tag . tagged DESC
EOQ ,
[ 'id' => $this -> getId ()],
options : [ 'offset' => $offset , 'limit' => $limit ],
2021-11-30 22:08:40 +00:00
),
2021-11-27 04:11:35 +00:00
);
} else {
2021-12-09 21:59:49 +00:00
$context_id = \is_int ( $context ) ? $context : $context -> getId ();
2021-11-27 04:11:35 +00:00
return Cache :: get (
2021-12-09 21:59:49 +00:00
self :: cacheKeys ( $this -> getId (), $context_id )[ 'tags' ],
[CORE][DB][ENTITY][Actor] Make DB::dql return a chunked array if selecting multiple entities, remove partitioning from callsite
`DB::dql('select a, b, from a join b')` would previously return `[a,
b, a, b, ...]` (or even `[b, a, b, a, ...]`), and now will return
`[[a, a, ...], [b, b, ...]]`. The issue would be further compounded
when selecting even more entities, where the order would be
unpredictable
2021-12-01 00:42:56 +00:00
fn () => DB :: dql (
<<< 'EOQ'
SELECT circle , tag
FROM actor_tag tag
JOIN actor_circle circle
WITH tag . tagger = circle . tagger
AND tag . tag = circle . tag
WHERE
tag . tagged = : id
AND ( circle . private != true
OR ( circle . tagger = : scoped
AND circle . private = true
)
)
ORDER BY tag . modified DESC , tag . tagged DESC
EOQ ,
2021-12-09 21:59:49 +00:00
[ 'id' => $this -> getId (), 'scoped' => $context_id ],
[CORE][DB][ENTITY][Actor] Make DB::dql return a chunked array if selecting multiple entities, remove partitioning from callsite
`DB::dql('select a, b, from a join b')` would previously return `[a,
b, a, b, ...]` (or even `[b, a, b, a, ...]`), and now will return
`[[a, a, ...], [b, b, ...]]`. The issue would be further compounded
when selecting even more entities, where the order would be
unpredictable
2021-12-01 00:42:56 +00:00
options : [ 'offset' => $offset , 'limit' => $limit ],
2021-11-30 22:08:40 +00:00
),
2021-11-27 04:11:35 +00:00
);
}
2020-08-08 17:10:25 +01:00
}
2021-11-27 04:11:35 +00:00
/**
2021-12-20 16:25:10 +00:00
* @ param array $tags array of strings to become self tags
2021-11-29 15:31:02 +00:00
* @ param null | array $existing array of existing self tags ( ActorTag [])
2021-11-28 13:09:04 +00:00
*
* @ return $this
2021-11-27 04:11:35 +00:00
*/
2021-12-20 16:25:10 +00:00
public function setSelfTags ( array $tags , ? array $existing = null ) : self
2020-08-08 17:10:25 +01:00
{
2021-12-19 17:09:00 +00:00
$tags = F\filter ( $tags , fn ( $tag ) => Nickname :: isCanonical ( $tag )); // TODO: Have an actual #Tag test
2021-12-09 22:23:17 +00:00
$tags = array_unique ( $tags );
2021-11-28 13:09:04 +00:00
if ( \is_null ( $existing )) {
2021-11-29 15:31:02 +00:00
[ $_ , $existing ] = $this -> getSelfTags ();
2020-08-08 17:10:25 +01:00
}
2021-11-29 15:31:02 +00:00
$existing_actor_tags = F\map ( $existing , fn ( $actor_tag ) => $actor_tag -> getTag ());
$tags_to_add = array_diff ( $tags , $existing_actor_tags );
$tags_to_remove = array_diff ( $existing_actor_tags , $tags );
$actor_tags_to_remove = F\filter ( $existing , fn ( $actor_tag ) => \in_array ( $actor_tag -> getTag (), $tags_to_remove ));
2021-11-27 04:11:35 +00:00
foreach ( $tags_to_add as $tag ) {
2021-11-28 13:09:04 +00:00
$canonical_tag = TagComponent :: canonicalTag ( $tag , $this -> getTopLanguage () -> getLocale ());
2021-12-19 17:09:00 +00:00
DB :: persist ( ActorCircle :: create ([ 'tagger' => $this -> getId (), 'tag' => $tag , 'private' => false ]));
DB :: persist ( ActorTag :: create ([ 'tagger' => $this -> id , 'tagged' => $this -> id , 'tag' => $tag , 'canonical' => $canonical_tag , 'use_canonical' => false ])); // TODO make use canonical configurable
2020-08-08 17:10:25 +01:00
}
2021-11-29 15:31:02 +00:00
foreach ( $actor_tags_to_remove as $actor_tag ) {
2021-12-19 17:09:00 +00:00
DB :: removeBy ( 'actor_tag' , [ 'tagger' => $this -> getId (), 'tagged' => $this -> getId (), 'tag' => $actor_tag -> getTag (), 'use_canonical' => $actor_tag -> getUseCanonical ()]);
DB :: removeBy ( 'actor_circle' , [ 'tagger' => $this -> getId (), 'tag' => $actor_tag -> getTag ()]); // TODO only remove if unused
2021-11-27 04:11:35 +00:00
}
2021-12-09 21:59:49 +00:00
Cache :: delete ( self :: cacheKeys ( $this -> getId ())[ 'tags' ]);
Cache :: delete ( self :: cacheKeys ( $this -> getId (), $this -> getId ())[ 'tags' ]);
2021-11-27 04:11:35 +00:00
return $this ;
2020-08-15 08:03:58 +01:00
}
2021-12-09 21:59:49 +00:00
private function getSubCount ( string $which , string $column ) : int
2020-08-15 08:03:58 +01:00
{
2021-10-28 17:34:01 +01:00
return Cache :: get (
2021-12-09 21:59:49 +00:00
self :: cacheKeys ( $this -> getId ())[ $which ],
fn () => DB :: dql (
" select count(s) from subscription s where s. { $column } = : { $column } " , // Not injecting the parameter value
[ $column => $this -> getId ()],
)[ 0 ][ 1 ] - ( $this -> getIsLocal () ? 1 : 0 ), // Remove self subscription if local
2021-10-28 17:34:01 +01:00
);
2020-08-15 08:03:58 +01:00
}
2021-12-09 21:59:49 +00:00
public function getSubscribersCount () : int
{
return $this -> getSubCount ( which : 'subscriber' , column : 'subscribed' );
}
2021-11-08 13:44:35 +00:00
public function getSubscribedCount ()
2020-08-15 08:03:58 +01:00
{
2021-12-09 21:59:49 +00:00
return $this -> getSubCount ( which : 'subscribed' , column : 'subscriber' );
2020-07-25 03:03:16 +01:00
}
2021-09-14 13:40:50 +01:00
public function isPerson () : bool
{
return ( $this -> roles & UserRoles :: BOT ) === 0 ;
}
/**
* Resolve an ambiguous nickname reference , checking in following order :
* - Actors that $sender subscribes to
* - Actors that subscribe to $sender
* - Any Actor
*
* @ param string $nickname validated nickname of
*
* @ throws NicknameException
*/
public function findRelativeActor ( string $nickname ) : ? self
{
// Will throw exception on invalid input.
$nickname = Nickname :: normalize ( $nickname , check_already_used : false );
2021-11-02 10:42:21 +00:00
return Cache :: get (
2021-12-09 21:59:49 +00:00
self :: cacheKeys ( $this -> getId (), $nickname )[ 'relative-nickname' ],
2021-11-28 13:09:04 +00:00
fn () => DB :: dql (
<<< 'EOF'
2021-12-09 21:59:49 +00:00
select a from actor a where
a . id in ( select fa . subscribed from subscription fa join actor aa with fa . subscribed = aa . id where fa . subscriber = : actor_id and aa . nickname = : nickname ) or
a . id in ( select fb . subscriber from subscription fb join actor ab with fb . subscriber = ab . id where fb . subscribed = : actor_id and ab . nickname = : nickname ) or
2021-11-02 11:11:51 +00:00
a . nickname = : nickname
EOF ,
2021-11-28 13:09:04 +00:00
[ 'nickname' => $nickname , 'actor_id' => $this -> getId ()],
[ 'limit' => 1 ],
)[ 0 ] ? ? null ,
2021-10-28 17:34:01 +01:00
);
2021-09-14 13:40:50 +01:00
}
2021-11-27 15:06:46 +00:00
public function getUri ( int $type = Router :: ABSOLUTE_URL ) : string
2021-09-14 13:40:50 +01:00
{
2021-11-27 15:06:46 +00:00
$uri = null ;
if ( Event :: handle ( 'StartGetActorUri' , [ $this , $type , & $uri ]) === Event :: next ) {
2021-11-29 23:58:42 +00:00
$uri = Router :: url ( 'actor_view_id' , [ 'id' => $this -> getId ()], $type );
2021-11-27 15:06:46 +00:00
Event :: handle ( 'EndGetActorUri' , [ $this , $type , & $uri ]);
}
return $uri ;
2021-09-14 13:40:50 +01:00
}
2021-11-27 15:06:46 +00:00
public function getUrl ( int $type = Router :: ABSOLUTE_URL ) : string
2021-09-14 13:40:50 +01:00
{
2021-11-27 15:06:46 +00:00
$url = null ;
if ( Event :: handle ( 'StartGetActorUrl' , [ $this , $type , & $url ]) === Event :: next ) {
if ( $this -> getIsLocal ()) {
$url = Router :: url ( 'actor_view_nickname' , [ 'nickname' => $this -> getNickname ()], $type );
2021-11-29 23:58:42 +00:00
} else {
return $this -> getUri ( $type );
2021-11-27 15:06:46 +00:00
}
Event :: handle ( 'EndGetActorUrl' , [ $this , $type , & $url ]);
}
return $url ;
2021-09-14 13:40:50 +01:00
}
2021-10-18 13:22:02 +01:00
public function getAliases () : array
{
return array_keys ( $this -> getAliasesWithIDs ());
}
public function getAliasesWithIDs () : array
{
$aliases = [];
$aliases [ $this -> getUri ( Router :: ABSOLUTE_URL )] = $this -> getId ();
$aliases [ $this -> getUrl ( Router :: ABSOLUTE_URL )] = $this -> getId ();
return $aliases ;
}
2021-11-28 13:09:04 +00:00
public function getTopLanguage () : Language
{
return ActorLanguage :: getActorLanguages ( $this , context : null )[ 0 ];
}
2021-11-01 19:43:23 +00:00
/**
2021-11-16 23:24:06 +00:00
* Get the most appropriate language for $this to use when
2021-11-01 19:43:23 +00:00
* referring to $context ( a reply or a group , for instance )
*
2021-11-11 12:29:55 +00:00
* @ return Language []
2021-11-01 19:43:23 +00:00
*/
2021-11-02 10:42:21 +00:00
public function getPreferredLanguageChoices ( ? self $context = null ) : array
2021-10-28 17:34:01 +01:00
{
2021-11-28 13:09:04 +00:00
$langs = ActorLanguage :: getActorLanguages ( $this , context : $context );
return array_merge ( ... F\map ( $langs , fn ( $l ) => $l -> toChoiceFormat ()));
}
2021-11-28 18:58:56 +00:00
public function isVisibleTo ( null | LocalUser | self $other ) : bool
2021-11-28 13:09:04 +00:00
{
return true ; // TODO
2021-10-28 17:34:01 +01:00
}
2020-03-29 20:56:35 +01:00
public static function schemaDef () : array
{
2021-10-28 17:34:01 +01:00
return [
2021-11-28 13:09:04 +00:00
'name' => 'actor' ,
2021-09-18 03:22:27 +01:00
'description' => 'local and remote users, groups and bots are actors, for instance' ,
2021-11-28 13:09:04 +00:00
'fields' => [
'id' => [ 'type' => 'serial' , 'not null' => true , 'description' => 'unique identifier' ],
'nickname' => [ 'type' => 'varchar' , 'length' => 64 , 'not null' => true , 'description' => 'nickname or username' ],
'fullname' => [ 'type' => 'text' , 'description' => 'display name' ],
2021-12-18 04:24:27 +00:00
'roles' => [ 'type' => 'int' , 'not null' => true , 'description' => 'Bitmap of permissions this actor has' ],
2021-12-11 22:19:37 +00:00
'type' => [ 'type' => 'int' , 'not null' => true , 'description' => 'The type of actor (person, group, bot, etc)' ],
2021-11-28 13:09:04 +00:00
'homepage' => [ 'type' => 'text' , 'description' => 'identifying URL' ],
'bio' => [ 'type' => 'text' , 'description' => 'descriptive biography' ],
'location' => [ 'type' => 'text' , 'description' => 'physical location' ],
'lat' => [ 'type' => 'numeric' , 'precision' => 10 , 'scale' => 7 , 'description' => 'latitude' ],
'lon' => [ 'type' => 'numeric' , 'precision' => 10 , 'scale' => 7 , 'description' => 'longitude' ],
'location_id' => [ 'type' => 'int' , 'description' => 'location id if possible' ],
2021-11-02 10:42:21 +00:00
'location_service' => [ 'type' => 'int' , 'description' => 'service used to obtain location id' ],
2021-11-28 13:09:04 +00:00
'is_local' => [ 'type' => 'bool' , 'not null' => true , 'description' => 'Does this actor have a LocalUser associated' ],
'created' => [ 'type' => 'datetime' , 'not null' => true , 'default' => 'CURRENT_TIMESTAMP' , 'description' => 'date this record was created' ],
'modified' => [ 'type' => 'timestamp' , 'not null' => true , 'default' => 'CURRENT_TIMESTAMP' , 'description' => 'date this record was modified' ],
2020-03-29 20:56:35 +01:00
],
'primary key' => [ 'id' ],
2021-11-28 13:09:04 +00:00
'indexes' => [
2021-09-18 03:22:27 +01:00
'actor_nickname_idx' => [ 'nickname' ],
2020-03-29 20:56:35 +01:00
],
2020-08-09 13:58:55 +01:00
'fulltext indexes' => [
2021-09-18 03:22:27 +01:00
'actor_fulltext_idx' => [ 'nickname' , 'fullname' , 'location' , 'bio' , 'homepage' ],
2020-08-09 13:58:55 +01:00
],
2020-03-29 20:56:35 +01:00
];
}
}