searchable; $query->where(function ($query) use ($fields, $search) { $query->where(array_shift($fields), 'LIKE', "%$search%"); foreach ($fields as $field) { $query->orWhere($field, 'LIKE', "$search%"); } }); } return $query; } public function scopeMentionBy($query, $search) { if ($search) { $fields = [ 'display_name', 'user_login' ]; $query->where(function ($query) use ($fields, $search) { $query->where(array_shift($fields), 'LIKE', "$search%"); foreach ($fields as $field) { $query->orWhere($field, 'LIKE', "$search%"); } }); } return $query; } /** * Accessor to get dynamic photo attribute * @return string */ public function getPhotoAttribute() { if ($photo = get_user_meta($this->ID, '_fcom_user_photo', true)) { return $photo; } if ($contact = $this->getContact()) { return $contact->photo; } if (empty($this->attributes['user_email'])) { if (defined('FLUENTCRM')) { $contact = Subscriber::where('user_id', $this->ID)->first(); if ($contact) { return $contact->photo; } } return ''; } $hash = md5(strtolower(trim($this->attributes['user_email']))); /** * Gravatar URL by Email * * @return string $gravatar url of the gravatar image */ $name = $this->attributes['display_name']; $fallback = ''; if ($name) { $fallback = '&d=https%3A%2F%2Fui-avatars.com%2Fapi%2F' . urlencode($name) . '/128'; } return apply_filters('fluent_crm/get_avatar', "https://www.gravatar.com/avatar/{$hash}?s=128" . $fallback, $this->attributes['user_email'] ); } public function getIsVerifiedAttribute() { return $this->isVerified(); } public function getContact() { if (!defined('FLUENTCRM')) { return null; } if ($this->user_email) { return Subscriber::where('user_id', $this->ID) ->orWhere('email', $this->user_email) ->first(); } return Subscriber::where('user_id', $this->ID) ->first(); } public function xprofile() { return $this->belongsTo(XProfile::class, 'ID', 'user_id'); } public function getGeneralData() { $user = get_user_by('ID', $this->ID); $fullName = ''; if ($user->first_name || $user->last_name) { $fullName = trim($user->first_name . ' ' . $user->last_name); } if (!$fullName) { $fullName = $user->display_name; } $contact = $this->getContact(); return [ 'is_contact' => (bool)$contact, 'first_name' => $user->first_name, 'last_name' => $user->last_name, 'full_name' => $fullName, 'display_name' => $fullName, 'bio' => $user->description, 'website' => $user->user_url, 'id' => $user->ID, 'user_id' => $user->ID, 'created_at' => $user->user_registered, 'photo' => $this->photo, 'username' => $this->username, 'is_verified' => $this->isVerified() ]; } public function spaces() { return $this->belongsToMany(BaseSpace::class, 'fcom_space_user', 'user_id', 'space_id') ->withPivot(['role', 'status', 'created_at']); } public function courses() { return $this->belongsToMany(Course::class, 'fcom_space_user', 'user_id', 'space_id') ->withPivot(['role', 'created_at']); } public function notificationSubscriptions() { return $this->hasMany(NotificationSubscription::class, 'user_id'); } public function space_pivot() { return $this->belongsTo(SpaceUserPivot::class, 'ID', 'user_id')->withoutGlobalScopes(); } public function notification_records() { return $this->hasMany(NotificationSubscriber::class, 'user_id', 'ID')->withoutGlobalScopes(); } public function crm_contact() { return $this->belongsTo(Contact::class, 'ID', 'user_id')->withoutGlobalScopes(); } public function community_role() { return $this->belongsTo(Meta::class, 'ID', 'object_id') ->where('meta_key', '_user_community_roles'); } public function updateCustomData($updateData, $removeSrc = false) { if (isset($updateData['first_name'])) { $firstName = sanitize_text_field($updateData['first_name']); $lastName = sanitize_text_field($updateData['last_name']); $userData = [ 'first_name' => $firstName, 'last_name' => $lastName, 'display_name' => trim($firstName . ' ' . $lastName), 'description' => isset($updateData['short_description']) ? sanitize_textarea_field($updateData['short_description']) : '', 'user_url' => isset($updateData['website']) ? esc_url($updateData['website']) : '', 'ID' => $this->ID ]; wp_update_user($userData); if ($contact = $this->getContact()) { $contact->fill(array_filter([ 'first_name' => $firstName, 'last_name' => $lastName ])); $dirtyFields = $contact->getDirty(); if ($dirtyFields) { $contact->save(); do_action('fluent_crm/contact_updated', $contact, $dirtyFields); } } } return $this; } public function getDisplayName() { $user = get_user_by('ID', $this->ID); $name = ''; if ($user->first_name || $user->last_name) { $name = trim($user->first_name . ' ' . $user->last_name); } if ($name) { return $name; } return $user->display_name; } public function getCustomMeta($key, $default = null) { $exist = Meta::where('object_type', 'user') ->where('object_id', $this->ID) ->where('meta_key', $key) ->first(); if ($exist && $exist->value) { return $exist->value; } return $default; } public function updateCustomMeta($key, $value) { $exist = Meta::where('object_type', 'user') ->where('object_id', $this->ID) ->where('meta_key', $key) ->first(); if ($exist) { $exist->value = $value; $exist->save(); return $exist; } return Meta::create([ 'object_type' => 'user', 'object_id' => $this->ID, 'meta_key' => $key, 'value' => $value ]); } public function getSpaceIds($cached = true) { if ($cached) { $ids = get_user_meta($this->ID, '_fcom_space_ids', true); if (!$ids || !is_array($ids)) { $ids = []; } return $ids; } $this->cacheAccessSpaces(); return get_user_meta($this->ID, '_fcom_space_ids', true); } public function getCommunityRoles() { if (Helper::isSiteAdmin($this->ID)) { return ['admin']; } return (array)$this->getCustomMeta('_user_community_roles', []); } public function isCommunityAdmin() { return in_array('admin', $this->getCommunityRoles()); } public function isCommunityModerator() { return !!array_intersect(['moderator', 'admin'], $this->getCommunityRoles()); } public function hasCourseManageAccess() { return !!array_intersect(['admin', 'course_creator', 'course_admin'], $this->getCommunityRoles()); } public function getSpaceRole($space) { $globalRoles = $this->getCommunityRoles(); if ($globalRoles) { if (in_array('admin', $globalRoles)) { return 'admin'; } } if ($space) { $spacePivot = SpaceUserPivot::where('space_id', $space->id) ->where('user_id', $this->ID) ->first(); if ($spacePivot) { if ($spacePivot->role != 'member') { return $spacePivot->role; } if (!in_array('moderator', $globalRoles)) { if ($spacePivot->status == 'pending') { return 'pending'; } return $spacePivot->role; } } } if (in_array('moderator', $globalRoles)) { return 'moderator'; } return ''; } public function cacheAccessSpaces() { $globalRoles = $this->getCommunityRoles(); if (array_intersect($globalRoles, ['admin', 'moderator'])) { $spaces = Space::all(); } else { $spaces = Space::whereHas('members', function ($query) { $query->where('user_id', $this->ID) ->where('status', 'active'); })->orWhere('privacy', 'public')->get(); } $spaceIds = $spaces->pluck('id')->toArray(); update_user_meta($this->ID, '_fcom_space_ids', $spaceIds); return $spaces; } protected function getRolePermissions($roles) { if (!$roles) { return apply_filters('fluent_community/user/permissions', [ 'read' => true ], $roles, $this); } $isAdmin = in_array('admin', $roles); $isModerator = array_intersect($roles, ['admin', 'moderator']); $permissions = [ 'community_admin' => $isAdmin ? 'admin' : false, 'community_moderator' => $isModerator, 'super_admin' => Helper::isSiteAdmin(), 'delete_any_feed' => $isModerator, 'edit_any_feed' => $isModerator, 'delete_any_comment' => $isModerator, 'edit_any_comment' => $isModerator, 'read' => true ]; if ($isAdmin || in_array('course_admin', $roles)) { $permissions['course_creator'] = true; $permissions['course_admin'] = true; } else if (in_array('course_creatror', $roles)) { $permissions['course_creator'] = true; } return apply_filters('fluent_community/user/permissions', $permissions, $roles, $this); } public function getPermissions($cached = true) { static $permissions; if ($permissions && $cached) { return $permissions; } $roles = $this->getCommunityRoles(); $permissions = $this->getRolePermissions($roles); return $permissions; } public function getSpacePermissions($space) { if (!$space) { return []; } $role = $this->getSpaceRole($space); $isRestrictedPost = Arr::get($space->settings, 'restricted_post_only') == 'yes'; if (!$role) { $permissions = [ 'can_create_post' => false, 'registered' => true, 'can_view_posts' => true, 'can_view_members' => true, 'is_pending' => false, 'is_non_member' => true, 'can_view_info' => $space->privacy !== 'secret' ]; if ($space->privacy === 'secret' || $space->privacy === 'private') { $permissions['can_view_posts'] = false; $permissions['can_view_members'] = false; } } else if ($role == 'pending') { $permissions = [ 'can_create_post' => false, 'registered' => true, 'can_view_posts' => true, 'can_view_members' => true, 'is_pending' => true, 'can_view_info' => $space->privacy !== 'secret' ]; if ($space->privacy === 'secret' || $space->privacy === 'private') { $permissions['can_view_posts'] = false; $permissions['can_view_members'] = false; } } else if ($role == 'member' || $role == 'student') { $permissions = [ 'can_create_post' => $isRestrictedPost ? false : true, 'registered' => true, 'can_view_posts' => true, 'can_view_members' => true, 'can_comment' => true, 'can_view_info' => true ]; } else { $permissions = [ 'can_create_post' => $isRestrictedPost ? in_array($role, ['admin', 'moderator']) : true, 'can_view_posts' => true, 'can_view_members' => true, 'registered' => true, 'community_admin' => $role === 'admin', 'community_moderator' => in_array($role, ['admin', 'moderator']), 'edit_any_feed' => $role === 'admin', 'delete_any_feed' => in_array($role, ['admin', 'moderator']), 'super_admin' => Helper::isSiteAdmin(), 'read' => true, 'can_remove_member' => $role === 'admin', 'can_add_member' => $role === 'admin', 'can_comment' => in_array($role, ['admin', 'moderator']), 'can_view_info' => true ]; } return apply_filters('fluent_community/user/space/permissions', $permissions, $space, $role, $this); } public function hasCommunityPermission($permission) { $permissions = $this->getPermissions(); if (isset($permissions[$permission])) { return $permissions[$permission]; } return false; } public function hasSpacePermission($permission, $space) { $permissions = $this->getSpacePermissions($space); if (isset($permissions[$permission])) { return $permissions[$permission]; } return false; } public function verifyCommunityPermission($permission) { if (!$this->hasCommunityPermission($permission)) { throw new \Exception('You do not have permission to do this action'); } return true; } public function verifySpacePermission($permission, $space) { if (!$space || !$this->hasSpacePermission($permission, $space)) { throw new \Exception('You do not have permission to do this action'); } return true; } public function canEditFeed($feed, $throwException = false) { $result = $feed->user_id == $this->ID || $this->hasCommunityPermission('edit_any_feed') || $this->hasSpacePermission('edit_any_feed', $feed->space_id); if (!$result && $throwException) { throw new \Exception('You do not have permission to do this action'); } return $result; } public function canDeleteFeed($feed, $throwException = false) { $result = $feed->user_id == $this->ID || $this->hasCommunityPermission('delete_any_feed') || $this->hasSpacePermission('delete_any_feed', $feed->space_id); if (!$result && $throwException) { throw new \Exception('You do not have permission to do this action'); } return $result; } public function can($permission, $space = null) { if ($space) { return $this->hasSpacePermission($permission, $space); } return $this->hasCommunityPermission($permission); } public function getUnreadNotificationCount() { return NotificationSubscriber::where('user_id', $this->ID) ->unread() ->count(); } public function getUnreadNotificationFeedIds() { $ids = Notification::whereHas('subscribers', function ($query) { return $query->where('user_id', $this->ID) ->unread(); })->pluck('feed_id')->toArray(); return array_values(array_unique($ids)); } public function isVerified() { return get_user_meta($this->ID, '_fcom_is_verified', true) == 'yes'; } public function syncXProfile($force = false) { $exist = $this->xprofile; if ($exist && !$force) { return $exist; } $createdAt = $this->user_registered; if (!$createdAt || $createdAt == '0000-00-00 00:00:00' || !strtotime($createdAt)) { $createdAt = gmdate('Y-m-d H:i:s'); } else { $timeDiff = time() - current_time('timestamp'); $createdAt = gmdate('Y-m-d H:i:s', strtotime($createdAt) - $timeDiff); } $data = [ 'user_id' => $this->ID, 'username' => ProfileHelper::generateUserName($this->ID), 'display_name' => $this->getDisplayName(), 'avatar' => $this->getPhotoAttribute(), 'is_verified' => $this->isVerified() ? 1 : 0, 'created_at' => $createdAt, 'short_description' => get_user_meta($this->ID, 'description', true), 'meta' => [ 'website' => $this->user_url, 'cover_photo' => get_user_meta($this->ID, '_fluent_cover_photo', true) ] ]; if ($exist) { unset($data['avatar']); unset($data['username']); $data['meta'] = wp_parse_args($exist->meta, $data['meta']); $exist->fill($data); $exist->save(); return $exist; } $counter = 1; $initialUserName = $data['username']; while (XProfile::where('username', $initialUserName)->first()) { $initialUserName = $data['username'] . '_' . $counter; $counter++; } $data['username'] = $initialUserName; return XProfile::create($data); } public function getUserMeta($metaKey, $default = null) { return get_user_meta($this->ID, $metaKey, true) ?? $default; } }