2020-06-07 19:04:43 +03:00
< ? php declare ( strict_types = 1 );
namespace openvk\Web\Models\Entities ;
2022-04-12 20:10:35 +03:00
use morphos\Gender ;
2020-06-11 23:21:49 +03:00
use openvk\Web\Themes\ { Themepack , Themepacks };
2020-06-07 19:04:43 +03:00
use openvk\Web\Util\DateTime ;
use openvk\Web\Models\RowModel ;
2021-10-07 11:48:55 +03:00
use openvk\Web\Models\Entities\ { Photo , Message , Correspondence , Gift };
2022-08-27 18:31:02 +03:00
use openvk\Web\Models\Repositories\ { Users , Clubs , Albums , Gifts , Notifications , Blacklists };
2022-02-05 21:09:37 +03:00
use openvk\Web\Models\Exceptions\InvalidUserNameException ;
2020-06-07 19:04:43 +03:00
use Nette\Database\Table\ActiveRow ;
use Chandler\Database\DatabaseConnection ;
use Chandler\Security\User as ChandlerUser ;
2022-04-12 20:10:35 +03:00
use function morphos\Russian\inflectName ;
2020-06-07 19:04:43 +03:00
class User extends RowModel
{
protected $tableName = " profiles " ;
const TYPE_DEFAULT = 0 ;
const TYPE_BOT = 1 ;
const SUBSCRIPTION_ABSENT = 0 ;
const SUBSCRIPTION_INCOMING = 1 ;
const SUBSCRIPTION_OUTGOING = 2 ;
const SUBSCRIPTION_MUTUAL = 3 ;
const PRIVACY_NO_ONE = 0 ;
const PRIVACY_ONLY_FRIENDS = 1 ;
const PRIVACY_ONLY_REGISTERED = 2 ;
const PRIVACY_EVERYONE = 3 ;
2021-01-07 19:19:36 +03:00
const NSFW_INTOLERANT = 0 ;
const NSFW_TOLERANT = 1 ;
const NSFW_FULL_TOLERANT = 2 ;
2022-03-27 16:43:20 +03:00
protected function _abstractRelationGenerator ( string $filename , int $page = 1 , int $limit = 6 ) : \Traversable
2020-06-07 19:04:43 +03:00
{
$id = $this -> getId ();
$query = " SELECT id FROM \n " . file_get_contents ( __DIR__ . " /../sql/ $filename .tsql " );
2022-03-27 16:43:20 +03:00
$query .= " \n LIMIT " . $limit . " OFFSET " . ( ( $page - 1 ) * $limit );
2020-06-07 19:04:43 +03:00
$rels = DatabaseConnection :: i () -> getConnection () -> query ( $query , $id , $id );
foreach ( $rels as $rel ) {
$rel = ( new Users ) -> get ( $rel -> id );
if ( ! $rel ) continue ;
yield $rel ;
}
}
protected function _abstractRelationCount ( string $filename ) : int
{
$id = $this -> getId ();
$query = " SELECT COUNT(*) AS cnt FROM \n " . file_get_contents ( __DIR__ . " /../sql/ $filename .tsql " );
return ( int ) DatabaseConnection :: i () -> getConnection () -> query ( $query , $id , $id ) -> fetch () -> cnt ;
}
function getId () : int
{
return $this -> getRecord () -> id ;
}
2020-06-11 23:21:49 +03:00
function getStyle () : string
2020-06-07 19:04:43 +03:00
{
return $this -> getRecord () -> style ;
}
2020-06-11 23:21:49 +03:00
function getTheme () : ? Themepack
{
return Themepacks :: i ()[ $this -> getStyle ()] ? ? NULL ;
}
2020-06-07 19:04:43 +03:00
function getStyleAvatar () : int
{
return $this -> getRecord () -> style_avatar ;
}
function hasMilkshakeEnabled () : bool
{
return ( bool ) $this -> getRecord () -> milkshake ;
}
2021-01-04 20:33:25 +03:00
function hasMicroblogEnabled () : bool
{
return ( bool ) $this -> getRecord () -> microblog ;
}
2022-05-23 11:18:06 +03:00
function getMainPage () : int
{
return $this -> getRecord () -> main_page ;
}
2020-06-07 19:04:43 +03:00
function getChandlerGUID () : string
{
return $this -> getRecord () -> user ;
}
function getChandlerUser () : ChandlerUser
{
return new ChandlerUser ( $this -> getRecord () -> ref ( " ChandlerUsers " , " user " ));
}
function getURL () : string
{
if ( ! is_null ( $this -> getShortCode ()))
return " / " . $this -> getShortCode ();
else
return " /id " . $this -> getId ();
}
2022-04-05 14:39:13 +03:00
function getAvatarUrl ( string $size = " miniscule " ) : string
2020-06-07 19:04:43 +03:00
{
2022-02-06 16:09:26 +03:00
$serverUrl = ovk_scheme ( true ) . $_SERVER [ " HTTP_HOST " ];
2020-09-29 23:03:55 +03:00
2020-06-07 19:04:43 +03:00
if ( $this -> getRecord () -> deleted )
2020-09-29 23:03:55 +03:00
return " $serverUrl /assets/packages/static/openvk/img/camera_200.png " ;
2020-06-07 19:04:43 +03:00
else if ( $this -> isBanned ())
2020-09-29 23:03:55 +03:00
return " $serverUrl /assets/packages/static/openvk/img/banned.jpg " ;
2020-06-07 19:04:43 +03:00
$avPhoto = $this -> getAvatarPhoto ();
if ( is_null ( $avPhoto ))
2020-09-29 23:03:55 +03:00
return " $serverUrl /assets/packages/static/openvk/img/camera_200.png " ;
2020-06-07 19:04:43 +03:00
else
2022-04-05 14:39:13 +03:00
return $avPhoto -> getURLBySizeId ( $size );
2020-06-07 19:04:43 +03:00
}
function getAvatarLink () : string
{
$avPhoto = $this -> getAvatarPhoto ();
if ( ! $avPhoto ) return " javascript:void(0) " ;
$pid = $avPhoto -> getPrettyId ();
$aid = ( new Albums ) -> getUserAvatarAlbum ( $this ) -> getId ();
return " /photo $pid ?from=album $aid " ;
}
function getAvatarPhoto () : ? Photo
{
$avAlbum = ( new Albums ) -> getUserAvatarAlbum ( $this );
$avCount = $avAlbum -> getPhotosCount ();
$avPhotos = $avAlbum -> getPhotos ( $avCount , 1 );
return iterator_to_array ( $avPhotos )[ 0 ] ? ? NULL ;
}
2022-05-30 11:09:45 +03:00
function getFirstName ( bool $pristine = false ) : string
2020-06-07 19:04:43 +03:00
{
2022-08-05 23:00:52 +03:00
$name = ( $this -> isDeleted () && ! $this -> isDeactivated () ? " DELETED " : mb_convert_case ( $this -> getRecord () -> first_name , MB_CASE_TITLE ));
2022-05-30 11:09:45 +03:00
if ((( $ts = tr ( " __transNames " )) !== " @__transNames " ) && ! $pristine )
2022-05-31 14:20:02 +03:00
return mb_convert_case ( transliterator_transliterate ( $ts , $name ), MB_CASE_TITLE );
2022-05-30 11:09:45 +03:00
else
return $name ;
2020-06-07 19:04:43 +03:00
}
2022-05-30 11:09:45 +03:00
function getLastName ( bool $pristine = false ) : string
2020-06-07 19:04:43 +03:00
{
2022-08-05 23:00:52 +03:00
$name = ( $this -> isDeleted () && ! $this -> isDeactivated () ? " DELETED " : mb_convert_case ( $this -> getRecord () -> last_name , MB_CASE_TITLE ));
2022-05-30 11:09:45 +03:00
if ((( $ts = tr ( " __transNames " )) !== " @__transNames " ) && ! $pristine )
2022-05-31 14:20:02 +03:00
return mb_convert_case ( transliterator_transliterate ( $ts , $name ), MB_CASE_TITLE );
2022-05-30 11:09:45 +03:00
else
return $name ;
2020-06-07 19:04:43 +03:00
}
function getPseudo () : ? string
{
2022-08-05 23:00:52 +03:00
return ( $this -> isDeleted () && ! $this -> isDeactivated () ? " DELETED " : $this -> getRecord () -> pseudo );
2020-06-07 19:04:43 +03:00
}
function getFullName () : string
{
2022-08-05 23:00:52 +03:00
if ( $this -> isDeleted () && ! $this -> isDeactivated ())
2020-06-07 19:04:43 +03:00
return " DELETED " ;
$pseudo = $this -> getPseudo ();
if ( ! $pseudo )
$pseudo = " " ;
else
$pseudo = " ( $pseudo ) " ;
return $this -> getFirstName () . $pseudo . $this -> getLastName ();
}
2022-04-12 20:10:35 +03:00
function getMorphedName ( string $case = " genitive " , bool $fullName = true ) : string
{
$name = $fullName ? ( $this -> getLastName () . " " . $this -> getFirstName ()) : $this -> getFirstName ();
if ( ! preg_match ( " %^[А -яё \ -]+ $ % " , $name ))
return $name ; # name is probably not russian
$inflected = inflectName ( $name , $case , $this -> isFemale () ? Gender :: FEMALE : Gender :: MALE );
return $inflected ? : $name ;
}
2020-06-07 19:04:43 +03:00
function getCanonicalName () : string
{
2022-08-05 23:00:52 +03:00
if ( $this -> isDeleted () && ! $this -> isDeactivated ())
2020-06-07 19:04:43 +03:00
return " DELETED " ;
2022-04-12 20:10:35 +03:00
else
return $this -> getFirstName () . " " . $this -> getLastName ();
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getPhone () : ? string
{
return $this -> getRecord () -> phone ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getEmail () : ? string
{
return $this -> getRecord () -> email ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getOnline () : DateTime
{
return new DateTime ( $this -> getRecord () -> online );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getDescription () : ? string
{
return $this -> getRecord () -> about ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getStatus () : ? string
{
return $this -> getRecord () -> status ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getShortCode () : ? string
{
return $this -> getRecord () -> shortcode ;
}
2022-04-12 20:10:35 +03:00
2021-11-03 00:07:26 +03:00
function getAlert () : ? string
{
return $this -> getRecord () -> alert ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getBanReason () : ? string
{
return $this -> getRecord () -> block_reason ;
}
2022-03-26 23:48:42 +03:00
function getBanInSupportReason () : ? string
{
return $this -> getRecord () -> block_in_support_reason ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getType () : int
{
return $this -> getRecord () -> type ;
}
2022-04-12 20:10:35 +03:00
2021-11-03 20:19:15 +03:00
function getCoins () : float
2020-06-07 19:04:43 +03:00
{
2021-10-12 12:15:55 +03:00
if ( ! OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " commerce " ])
2021-11-03 20:19:15 +03:00
return 0.0 ;
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return $this -> getRecord () -> coins ;
}
2022-04-12 20:10:35 +03:00
2021-10-07 11:47:30 +03:00
function getRating () : int
{
2021-10-12 12:15:55 +03:00
return OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " commerce " ] ? $this -> getRecord () -> rating : 0 ;
2021-10-07 11:47:30 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getReputation () : int
{
return $this -> getRecord () -> reputation ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getRegistrationTime () : DateTime
{
return new DateTime ( $this -> getRecord () -> since -> getTimestamp ());
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getRegistrationIP () : string
{
return $this -> getRecord () -> registering_ip ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getHometown () : ? string
{
return $this -> getRecord () -> hometown ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getPoliticalViews () : int
{
return $this -> getRecord () -> polit_views ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getMaritalStatus () : int
{
return $this -> getRecord () -> marital_status ;
}
2022-05-30 10:46:27 +03:00
function getLocalizedMaritalStatus () : string
{
$status = $this -> getMaritalStatus ();
$string = " relationship_ $status " ;
if ( $this -> isFemale ()) {
$res = tr ( $string . " _fem " );
if ( $res != ( " @ " . $string . " _fem " ))
return $res ; # If fem version exists, return
}
return tr ( $string );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getContactEmail () : ? string
{
return $this -> getRecord () -> email_contact ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getTelegram () : ? string
{
return $this -> getRecord () -> telegram ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getInterests () : ? string
{
return $this -> getRecord () -> interests ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFavoriteMusic () : ? string
{
return $this -> getRecord () -> fav_music ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFavoriteFilms () : ? string
{
return $this -> getRecord () -> fav_films ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFavoriteShows () : ? string
{
return $this -> getRecord () -> fav_shows ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFavoriteBooks () : ? string
{
return $this -> getRecord () -> fav_books ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFavoriteQuote () : ? string
{
return $this -> getRecord () -> fav_quote ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getCity () : ? string
{
return $this -> getRecord () -> city ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getPhysicalAddress () : ? string
{
return $this -> getRecord () -> address ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getNotificationOffset () : int
{
return $this -> getRecord () -> notification_offset ;
}
2021-09-13 19:34:02 +03:00
2021-12-14 18:53:44 +03:00
function getBirthday () : ? DateTime
2021-09-13 19:34:02 +03:00
{
2022-07-09 17:33:55 +03:00
if ( is_null ( $this -> getRecord () -> birthday ))
return NULL ;
else
return new DateTime ( $this -> getRecord () -> birthday );
}
function getBirthdayPrivacy () : int
{
return $this -> getRecord () -> birthday_privacy ;
2021-09-13 19:34:02 +03:00
}
2021-11-27 21:02:37 +03:00
function getAge () : ? int
{
2021-12-25 14:21:39 +03:00
return ( int ) floor (( time () - $this -> getBirthday () -> timestamp ()) / YEAR );
2021-11-27 21:02:37 +03:00
}
2022-04-12 20:10:35 +03:00
2021-12-02 18:31:32 +03:00
function get2faSecret () : ? string
{
return $this -> getRecord ()[ " 2fa_secret " ];
}
function is2faEnabled () : bool
{
return ! is_null ( $this -> get2faSecret ());
}
2020-06-07 19:04:43 +03:00
function updateNotificationOffset () : void
{
$this -> stateChanges ( " notification_offset " , time ());
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getLeftMenuItemStatus ( string $id ) : bool
{
return ( bool ) bmask ( $this -> getRecord () -> left_menu , [
" length " => 1 ,
" mappings " => [
" photos " ,
" videos " ,
" messages " ,
" notes " ,
" groups " ,
" news " ,
2021-12-17 19:58:31 +03:00
" links " ,
2022-01-03 22:13:53 +03:00
" poster " ,
2020-06-07 19:04:43 +03:00
],
]) -> get ( $id );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getPrivacySetting ( string $id ) : int
{
return ( int ) bmask ( $this -> getRecord () -> privacy , [
" length " => 2 ,
" mappings " => [
" page.read " ,
" page.info.read " ,
" groups.read " ,
" photos.read " ,
" videos.read " ,
" notes.read " ,
" friends.read " ,
" friends.add " ,
" wall.write " ,
2021-12-28 12:40:14 +03:00
" messages.write " ,
2020-06-07 19:04:43 +03:00
],
]) -> get ( $id );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getPrivacyPermission ( string $permission , ? User $user = NULL ) : bool
{
$permStatus = $this -> getPrivacySetting ( $permission );
if ( ! $user )
return $permStatus === User :: PRIVACY_EVERYONE ;
else if ( $user -> getId () === $this -> getId ())
return true ;
2022-08-27 18:31:02 +03:00
else if (( new Blacklists ) -> isBanned ( $this , $user )) {
2022-08-27 23:23:05 +03:00
if ( $user -> isAdmin () && ! OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " security " ][ " blacklists " ][ " applyToAdmins " ])
2022-08-27 18:31:02 +03:00
return true ;
return false ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
switch ( $permStatus ) {
case User :: PRIVACY_ONLY_FRIENDS :
return $this -> getSubscriptionStatus ( $user ) === User :: SUBSCRIPTION_MUTUAL ;
case User :: PRIVACY_ONLY_REGISTERED :
case User :: PRIVACY_EVERYONE :
return true ;
default :
return false ;
}
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getProfileCompletenessReport () : object
{
$incompleteness = 0 ;
$unfilled = [];
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
if ( ! $this -> getRecord () -> status ) {
$unfilled [] = " status " ;
2021-02-06 23:38:39 +03:00
$incompleteness += 15 ;
2020-06-07 19:04:43 +03:00
}
if ( ! $this -> getRecord () -> telegram ) {
$unfilled [] = " telegram " ;
2021-02-06 23:38:39 +03:00
$incompleteness += 15 ;
2020-06-07 19:04:43 +03:00
}
if ( ! $this -> getRecord () -> email ) {
$unfilled [] = " email " ;
$incompleteness += 20 ;
}
if ( ! $this -> getRecord () -> city ) {
$unfilled [] = " city " ;
$incompleteness += 20 ;
}
if ( ! $this -> getRecord () -> interests ) {
$unfilled [] = " interests " ;
$incompleteness += 20 ;
}
2022-04-12 20:10:35 +03:00
2021-10-09 22:42:20 +03:00
$total = max ( 100 - $incompleteness + $this -> getRating (), 0 );
2021-10-09 22:44:48 +03:00
if ( ovkGetQuirk ( " profile.rating-bar-behaviour " ) === 0 )
2021-10-10 00:05:20 +03:00
if ( $total >= 100 )
2021-10-12 12:15:55 +03:00
$percent = round (( $total / 10 ** strlen ( strval ( $total ))) * 100 , 0 );
2021-10-09 22:42:20 +03:00
else
2021-10-12 12:15:55 +03:00
$percent = min ( $total , 100 );
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return ( object ) [
2021-10-09 22:42:20 +03:00
" total " => $total ,
" percent " => $percent ,
2020-06-07 19:04:43 +03:00
" unfilled " => $unfilled ,
];
}
2022-04-12 20:10:35 +03:00
2022-03-27 16:43:20 +03:00
function getFriends ( int $page = 1 , int $limit = 6 ) : \Traversable
2020-06-07 19:04:43 +03:00
{
2022-03-27 16:43:20 +03:00
return $this -> _abstractRelationGenerator ( " get-friends " , $page , $limit );
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFriendsCount () : int
{
return $this -> _abstractRelationCount ( " get-friends " );
}
2022-04-12 20:10:35 +03:00
2022-07-31 14:33:23 +03:00
function getFriendsOnline ( int $page = 1 , int $limit = 6 ) : \Traversable
{
return $this -> _abstractRelationGenerator ( " get-online-friends " , $page , $limit );
}
function getFriendsOnlineCount () : int
{
return $this -> _abstractRelationCount ( " get-online-friends " );
}
2022-03-27 16:43:20 +03:00
function getFollowers ( int $page = 1 , int $limit = 6 ) : \Traversable
2020-06-07 19:04:43 +03:00
{
2022-03-27 16:43:20 +03:00
return $this -> _abstractRelationGenerator ( " get-followers " , $page , $limit );
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getFollowersCount () : int
{
return $this -> _abstractRelationCount ( " get-followers " );
}
2022-04-12 20:10:35 +03:00
2022-03-27 16:43:20 +03:00
function getSubscriptions ( int $page = 1 , int $limit = 6 ) : \Traversable
2020-06-07 19:04:43 +03:00
{
2022-03-27 16:43:20 +03:00
return $this -> _abstractRelationGenerator ( " get-subscriptions-user " , $page , $limit );
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getSubscriptionsCount () : int
{
return $this -> _abstractRelationCount ( " get-subscriptions-user " );
}
2021-01-07 19:19:36 +03:00
function getUnreadMessagesCount () : int
{
return sizeof ( DatabaseConnection :: i () -> getContext () -> table ( " messages " ) -> where ([ " recipient_id " => $this -> getId (), " unread " => 1 ]));
}
2022-04-12 20:10:35 +03:00
2021-11-20 13:47:59 +03:00
function getClubs ( int $page = 1 , bool $admin = false ) : \Traversable
2020-06-07 19:04:43 +03:00
{
2021-12-03 21:08:50 +03:00
if ( $admin ) {
$id = $this -> getId ();
$query = " SELECT `id` FROM `groups` WHERE `owner` = ? UNION SELECT `club` as `id` FROM `group_coadmins` WHERE `user` = ? " ;
$query .= " LIMIT " . OPENVK_DEFAULT_PER_PAGE . " OFFSET " . ( $page - 1 ) * OPENVK_DEFAULT_PER_PAGE ;
$sel = DatabaseConnection :: i () -> getConnection () -> query ( $query , $id , $id );
foreach ( $sel as $target ) {
$target = ( new Clubs ) -> get ( $target -> id );
if ( ! $target ) continue ;
yield $target ;
}
} else {
$sel = $this -> getRecord () -> related ( " subscriptions.follower " ) -> page ( $page , OPENVK_DEFAULT_PER_PAGE );
foreach ( $sel -> where ( " model " , " openvk \\ Web \\ Models \\ Entities \\ Club " ) as $target ) {
$target = ( new Clubs ) -> get ( $target -> target );
if ( ! $target ) continue ;
yield $target ;
}
2020-06-07 19:04:43 +03:00
}
}
2022-04-12 20:10:35 +03:00
2021-11-20 13:47:59 +03:00
function getClubCount ( bool $admin = false ) : int
2020-06-07 19:04:43 +03:00
{
2021-12-03 21:08:50 +03:00
if ( $admin ) {
$id = $this -> getId ();
$query = " SELECT COUNT(*) AS `cnt` FROM (SELECT `id` FROM `groups` WHERE `owner` = ? UNION SELECT `club` as `id` FROM `group_coadmins` WHERE `user` = ?) u0; " ;
return ( int ) DatabaseConnection :: i () -> getConnection () -> query ( $query , $id , $id ) -> fetch () -> cnt ;
} else {
$sel = $this -> getRecord () -> related ( " subscriptions.follower " );
$sel = $sel -> where ( " model " , " openvk \\ Web \\ Models \\ Entities \\ Club " );
2021-11-20 13:47:59 +03:00
2021-12-03 21:08:50 +03:00
return sizeof ( $sel );
2021-11-20 13:47:59 +03:00
}
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2021-11-10 11:45:06 +03:00
function getPinnedClubs () : \Traversable
{
foreach ( $this -> getRecord () -> related ( " groups.owner " ) -> where ( " owner_club_pinned " , true ) as $target ) {
$target = ( new Clubs ) -> get ( $target -> id );
if ( ! $target ) continue ;
yield $target ;
}
foreach ( $this -> getRecord () -> related ( " group_coadmins.user " ) -> where ( " club_pinned " , true ) as $target ) {
$target = ( new Clubs ) -> get ( $target -> club );
if ( ! $target ) continue ;
yield $target ;
}
}
function getPinnedClubCount () : int
{
return sizeof ( $this -> getRecord () -> related ( " groups.owner " ) -> where ( " owner_club_pinned " , true )) + sizeof ( $this -> getRecord () -> related ( " group_coadmins.user " ) -> where ( " club_pinned " , true ));
}
function isClubPinned ( Club $club ) : bool
{
if ( $club -> getOwner () -> getId () === $this -> getId ())
return $club -> isOwnerClubPinned ();
$manager = $club -> getManager ( $this );
if ( ! is_null ( $manager ))
return $manager -> isClubPinned ();
2021-12-24 23:08:03 +03:00
return false ;
2021-11-10 11:45:06 +03:00
}
2020-06-07 19:04:43 +03:00
function getMeetings ( int $page = 1 ) : \Traversable
{
$sel = $this -> getRecord () -> related ( " event_turnouts.user " ) -> page ( $page , OPENVK_DEFAULT_PER_PAGE );
foreach ( $sel as $target ) {
$target = ( new Clubs ) -> get ( $target -> event );
if ( ! $target ) continue ;
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
yield $target ;
}
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getMeetingCount () : int
{
return sizeof ( $this -> getRecord () -> related ( " event_turnouts.user " ));
}
2022-04-12 20:10:35 +03:00
2021-10-07 11:48:55 +03:00
function getGifts ( int $page = 1 , ? int $perPage = NULL ) : \Traversable
{
$gifts = $this -> getRecord () -> related ( " gift_user_relations.receiver " ) -> order ( " sent DESC " ) -> page ( $page , $perPage ? ? OPENVK_DEFAULT_PER_PAGE );
foreach ( $gifts as $rel ) {
yield ( object ) [
" sender " => ( new Users ) -> get ( $rel -> sender ),
" gift " => ( new Gifts ) -> get ( $rel -> gift ),
" caption " => $rel -> comment ,
" anon " => $rel -> anonymous ,
" sent " => new DateTime ( $rel -> sent ),
];
}
}
2022-04-12 20:10:35 +03:00
2021-10-07 11:48:55 +03:00
function getGiftCount () : int
{
return sizeof ( $this -> getRecord () -> related ( " gift_user_relations.receiver " ));
}
2021-12-02 18:31:32 +03:00
function get2faBackupCodes () : \Traversable
{
$sel = $this -> getRecord () -> related ( " 2fa_backup_codes.owner " );
foreach ( $sel as $target )
yield $target -> code ;
}
function get2faBackupCodeCount () : int
{
return sizeof ( $this -> getRecord () -> related ( " 2fa_backup_codes.owner " ));
}
function generate2faBackupCodes () : void
{
$codes = [];
for ( $i = 0 ; $i < 10 - $this -> get2faBackupCodeCount (); $i ++ ) {
$codes [] = [
owner => $this -> getId (),
code => random_int ( 10000000 , 99999999 )
];
}
if ( sizeof ( $codes ) > 0 )
DatabaseConnection :: i () -> getContext () -> table ( " 2fa_backup_codes " ) -> insert ( $codes );
}
function use2faBackupCode ( int $code ) : bool
{
2022-04-12 20:10:35 +03:00
return ( bool ) $this -> getRecord () -> related ( " 2fa_backup_codes.owner " ) -> where ( " code " , $code ) -> delete ();
2021-12-02 18:31:32 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getSubscriptionStatus ( User $user ) : int
{
$subbed = ! is_null ( $this -> getRecord () -> related ( " subscriptions.follower " ) -> where ([
" model " => static :: class ,
" target " => $user -> getId (),
]) -> fetch ());
$followed = ! is_null ( $this -> getRecord () -> related ( " subscriptions.target " ) -> where ([
" model " => static :: class ,
" follower " => $user -> getId (),
]) -> fetch ());
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
if ( $subbed && $followed ) return User :: SUBSCRIPTION_MUTUAL ;
if ( $subbed ) return User :: SUBSCRIPTION_INCOMING ;
if ( $followed ) return User :: SUBSCRIPTION_OUTGOING ;
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return User :: SUBSCRIPTION_ABSENT ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getNotificationsCount ( bool $archived = false ) : int
{
return ( new Notifications ) -> getNotificationCountByUser ( $this , $this -> getNotificationOffset (), $archived );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getNotifications ( int $page , bool $archived = false ) : \Traversable
{
return ( new Notifications ) -> getNotificationsByUser ( $this , $this -> getNotificationOffset (), $archived , $page );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getPendingPhoneVerification () : ? ActiveRow
{
return $this -> getRecord () -> ref ( " number_verification " , " id " );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function getRefLinkId () : string
{
2021-09-13 06:22:05 +03:00
$hash = hash_hmac ( " Snefru " , ( string ) $this -> getId (), CHANDLER_ROOT_CONF [ " security " ][ " secret " ], true );
2022-04-12 20:10:35 +03:00
2021-09-13 06:22:05 +03:00
return dechex ( $this -> getId ()) . " " . base64_encode ( $hash );
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2021-01-07 19:19:36 +03:00
function getNsfwTolerance () : int
{
return $this -> getRecord () -> nsfw_tolerance ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function isFemale () : bool
{
return ( bool ) $this -> getRecord () -> sex ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function isVerified () : bool
{
return ( bool ) $this -> getRecord () -> verified ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function isBanned () : bool
{
return ! is_null ( $this -> getBanReason ());
}
2022-03-26 23:48:42 +03:00
function isBannedInSupport () : bool
{
return ! is_null ( $this -> getBanInSupportReason ());
}
2022-04-12 20:10:35 +03:00
2021-11-04 14:45:30 +03:00
function isOnline () : bool
{
return time () - $this -> getRecord () -> online <= 300 ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function prefersNotToSeeRating () : bool
{
return ! (( bool ) $this -> getRecord () -> show_rating );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function hasPendingNumberChange () : bool
{
return ! is_null ( $this -> getPendingPhoneVerification ());
}
2022-04-12 20:10:35 +03:00
2021-10-07 11:48:55 +03:00
function gift ( User $sender , Gift $gift , ? string $comment = NULL , bool $anonymous = false ) : void
{
DatabaseConnection :: i () -> getContext () -> table ( " gift_user_relations " ) -> insert ([
" sender " => $sender -> getId (),
" receiver " => $this -> getId (),
" gift " => $gift -> getId (),
" comment " => $comment ,
" anonymous " => $anonymous ,
" sent " => time (),
]);
}
2022-04-12 20:10:35 +03:00
2021-12-25 23:32:15 +03:00
function ban ( string $reason , bool $deleteSubscriptions = true ) : void
{
if ( $deleteSubscriptions ) {
$subs = DatabaseConnection :: i () -> getContext () -> table ( " subscriptions " );
$subs = $subs -> where (
" follower = ? OR (target = ? AND model = ?) " ,
$this -> getId (),
$this -> getId (),
get_class ( $this ),
);
$subs -> delete ();
}
2022-04-12 20:10:35 +03:00
2020-07-17 19:26:59 +03:00
$this -> setBlock_Reason ( $reason );
$this -> save ();
}
2022-04-12 20:10:35 +03:00
2022-08-05 23:00:52 +03:00
function deactivate ( ? string $reason ) : void
{
$this -> setDeleted ( 1 );
$this -> setDeact_Date ( time () + ( MONTH * 7 ));
$this -> setDeact_Reason ( $reason );
$this -> save ();
}
function reactivate () : void
{
$this -> setDeleted ( 0 );
$this -> setDeact_Date ( 0 );
$this -> setDeact_Reason ( " " );
$this -> save ();
}
function getDeactivationDate () : DateTime
{
return new DateTime ( $this -> getRecord () -> deact_date );
}
2020-06-07 19:04:43 +03:00
function verifyNumber ( string $code ) : bool
{
$ver = $this -> getPendingPhoneVerification ();
if ( ! $ver ) return false ;
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
try {
if ( sodium_memcmp (( string ) $ver -> code , $code ) === - 1 ) return false ;
} catch ( \SodiumException $ex ) {
return false ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
$this -> setPhone ( $ver -> number );
$this -> save ();
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
DatabaseConnection :: i () -> getContext ()
-> table ( " number_verification " )
-> where ( " user " , $this -> getId ())
-> delete ();
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return true ;
}
2022-04-12 20:10:35 +03:00
2022-02-05 21:09:37 +03:00
function setFirst_Name ( string $firstName ) : void
{
$firstName = mb_convert_case ( $firstName , MB_CASE_TITLE );
2022-02-08 13:15:29 +03:00
if ( ! preg_match ( '%^[\p{Lu}\p{Lo}]\p{Mn}?(?:[\p{L&}\p{Lo}]\p{Mn}?){1,16}$%u' , $firstName ))
2022-02-05 21:09:37 +03:00
throw new InvalidUserNameException ;
2022-04-12 20:10:35 +03:00
2022-02-05 21:09:37 +03:00
$this -> stateChanges ( " first_name " , $firstName );
}
2022-04-12 20:10:35 +03:00
2022-02-05 21:09:37 +03:00
function setLast_Name ( string $lastName ) : void
{
2022-02-07 20:16:47 +03:00
if ( ! empty ( $lastName ))
{
$lastName = mb_convert_case ( $lastName , MB_CASE_TITLE );
2022-02-08 13:15:29 +03:00
if ( ! preg_match ( '%^[\p{Lu}\p{Lo}]\p{Mn}?([\p{L&}\p{Lo}]\p{Mn}?){1,16}(\-\g<1>+)?$%u' , $lastName ))
2022-02-07 20:16:47 +03:00
throw new InvalidUserNameException ;
}
2022-04-12 20:10:35 +03:00
2022-02-05 21:09:37 +03:00
$this -> stateChanges ( " last_name " , $lastName );
}
2022-04-12 20:10:35 +03:00
2021-01-07 19:19:36 +03:00
function setNsfwTolerance ( int $tolerance ) : void
{
$this -> stateChanges ( " nsfw_tolerance " , $tolerance );
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function setPrivacySetting ( string $id , int $status ) : void
{
$this -> stateChanges ( " privacy " , bmask ( $this -> changes [ " privacy " ] ? ? $this -> getRecord () -> privacy , [
" length " => 2 ,
" mappings " => [
" page.read " ,
" page.info.read " ,
" groups.read " ,
" photos.read " ,
" videos.read " ,
" notes.read " ,
" friends.read " ,
" friends.add " ,
" wall.write " ,
2021-12-28 12:40:14 +03:00
" messages.write " ,
2020-06-07 19:04:43 +03:00
],
]) -> set ( $id , $status ) -> toInteger ());
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function setLeftMenuItemStatus ( string $id , bool $status ) : void
{
$mask = bmask ( $this -> changes [ " left_menu " ] ? ? $this -> getRecord () -> left_menu , [
" length " => 1 ,
" mappings " => [
" photos " ,
" videos " ,
" messages " ,
" notes " ,
" groups " ,
" news " ,
2021-12-17 19:58:31 +03:00
" links " ,
2022-01-03 22:13:53 +03:00
" poster " ,
2020-06-07 19:04:43 +03:00
],
]) -> set ( $id , ( int ) $status ) -> toInteger ();
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
$this -> stateChanges ( " left_menu " , $mask );
}
2022-04-12 20:10:35 +03:00
2021-10-13 23:41:12 +03:00
function setShortCode ( ? string $code = NULL , bool $force = false ) : ? bool
2020-06-07 19:04:43 +03:00
{
if ( ! is_null ( $code )) {
2021-10-13 23:41:12 +03:00
if ( strlen ( $code ) < OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " shortcodes " ][ " minLength " ] && ! $force )
return false ;
2020-06-07 19:04:43 +03:00
if ( ! preg_match ( " %^[a-z][a-z0-9 \\ . \\ _] { 0,30}[a-z0-9] $ % " , $code ))
return false ;
if ( in_array ( $code , OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " shortcodes " ][ " forbiddenNames " ]))
return false ;
if ( \Chandler\MVC\Routing\Router :: i () -> getMatchingRoute ( " / $code " )[ 0 ] -> presenter !== " UnknownTextRouteStrategy " )
return false ;
2022-04-12 20:10:35 +03:00
2021-10-13 23:41:12 +03:00
$pClub = DatabaseConnection :: i () -> getContext () -> table ( " groups " ) -> where ( " shortcode " , $code ) -> fetch ();
if ( ! is_null ( $pClub ))
return false ;
2020-06-07 19:04:43 +03:00
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
$this -> stateChanges ( " shortcode " , $code );
return true ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
function setPhoneWithVerification ( string $phone ) : string
{
$code = unpack ( " S " , openssl_random_pseudo_bytes ( 2 ))[ 1 ];
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
if ( $this -> hasPendingNumberChange ()) {
DatabaseConnection :: i () -> getContext ()
-> table ( " number_verification " )
-> where ( " user " , $this -> getId ())
-> update ([ " number " => $phone , " code " => $code ]);
} else {
DatabaseConnection :: i () -> getContext ()
-> table ( " number_verification " )
-> insert ([ " user " => $this -> getId (), " number " => $phone , " code " => $code ]);
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return ( string ) $code ;
}
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
# KABOBSQL temporary fix
# Tuesday, the 7th of January 2020 @ 22:43 <Menhera>: implementing quick fix to this problem and monitoring
# NOTICE: this is an ongoing conversation, add your comments just above this line. Thanks!
function setOnline ( int $time ) : bool
{
$this -> stateChanges ( " shortcode " , $this -> getRecord () -> shortcode ); #fix KABOBSQL
$this -> stateChanges ( " online " , $time );
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return true ;
}
2022-04-12 20:10:35 +03:00
2022-05-07 16:00:25 +03:00
function changeEmail ( string $email ) : void
2022-05-06 17:17:08 +03:00
{
DatabaseConnection :: i () -> getContext () -> table ( " ChandlerUsers " )
-> where ( " id " , $this -> getChandlerUser () -> getId ()) -> update ([
" login " => $email
]);
$this -> stateChanges ( " email " , $email );
$this -> save ();
}
2020-06-07 19:04:43 +03:00
function adminNotify ( string $message ) : bool
{
$admId = OPENVK_ROOT_CONF [ " openvk " ][ " preferences " ][ " support " ][ " adminAccount " ];
if ( ! $admId )
return false ;
else if ( is_null ( $admin = ( new Users ) -> get ( $admId )))
return false ;
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
$cor = new Correspondence ( $admin , $this );
$msg = new Message ;
$msg -> setContent ( $message );
$cor -> sendMessage ( $msg , true );
2022-04-12 20:10:35 +03:00
2020-06-07 19:04:43 +03:00
return true ;
}
function isDeleted () : bool
{
2022-08-05 23:29:31 +03:00
if ( $this -> getRecord () -> deleted == 1 )
2022-01-31 14:45:53 +03:00
return TRUE ;
else
return FALSE ;
2020-06-07 19:04:43 +03:00
}
2022-08-05 23:00:52 +03:00
function isDeactivated () : bool
{
2022-08-05 23:29:31 +03:00
if ( $this -> getDeactivationDate () -> timestamp () > time ())
2022-08-05 23:00:52 +03:00
return TRUE ;
else
return FALSE ;
}
2021-09-11 01:33:45 +03:00
/**
* 0 - Default status
* 1 - Incognito online status
* 2 - Page of a dead person
*/
function onlineStatus () : int
{
switch ( $this -> getRecord () -> online ) {
case 1 :
return 1 ;
break ;
case 2 :
return 2 ;
break ;
2022-04-12 20:10:35 +03:00
2021-09-11 01:33:45 +03:00
default :
return 0 ;
break ;
}
}
2021-11-13 15:13:44 +03:00
function getWebsite () : ? string
{
return $this -> getRecord () -> website ;
}
2022-01-31 14:45:53 +03:00
2022-05-08 13:06:26 +03:00
# ты устрица
2022-01-31 14:45:53 +03:00
function isActivated () : bool
{
return ( bool ) $this -> getRecord () -> activated ;
}
2022-08-27 18:31:02 +03:00
function isAdmin () : bool
{
return $this -> getChandlerUser () -> can ( " access " ) -> model ( " admin " ) -> whichBelongsTo ( NULL );
}
2020-06-07 19:04:43 +03:00
use Traits\TSubscribable ;
}