PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.10.0
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.10.0
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
← All changes | app/Models/XProfile.php +168 -19 1.0.922.10.0 View file →
@@ -6,9 +6,12 @@
6 6 use FluentCommunity\App\Functions\Utility;
7 7 use FluentCommunity\App\Models\Contact;
8 8 use FluentCommunity\App\Models\Feed;
9 9 use FluentCommunity\App\Models\User;
10 +use FluentCommunity\App\Services\Helper;
10 11 use FluentCommunity\Framework\Support\Arr;
12 +use FluentCommunity\Modules\Course\Model\Course;
13 +use FluentCommunityPro\App\Models\Follow;
11 14 use FluentCrm\App\Models\Subscriber;
12 15
13 16 /**
14 17 * FluentCommunity XProfile Model
@@ -17,14 +20,34 @@
17 20 *
18 21 * @package FluentCommunity\App\Models
19 22 *
20 23 * @version 1.1.0
24 + *
25 + * @property int $id
26 + * @property int $user_id
27 + * @property int $total_points
28 + * @property string|null $username
29 + * @property string $status
30 + * @property int $is_verified
31 + * @property string|null $display_name
32 + * @property string|null $avatar
33 + * @property string|null $short_description
34 + * @property string|null $last_activity
35 + * @property mixed $meta
36 + * @property mixed $custom_fields
37 + * @property object|null $created_at
38 + * @property-read mixed $badge
39 + * @property-read string $permalink
40 + * @property-read \FluentCommunity\App\Models\User|null $user
41 + * @property int|null $compilation_score
42 + * @property string|null $user_email
43 + * @property int|null $ID
21 44 */
22 45 class XProfile extends Model
23 46 {
24 47 protected $table = 'fcom_xprofile';
25 48
26 - protected $guarded = ['id'];
49 + protected $guarded = [ 'id' ];
27 50
28 51 protected $primaryKey = 'user_id';
29 52
30 53 protected $casts = [
@@ -36,9 +59,8 @@
36 59 protected $fillable = [
37 60 'user_id',
38 61 'total_points',
39 62 'username',
40 - 'total_points',
41 63 'status',
42 64 'is_verified',
43 65 'display_name',
44 66 'avatar',
@@ -44,26 +66,28 @@
44 66 'avatar',
45 67 'short_description',
46 68 'last_activity',
47 69 'meta',
48 - 'created_at'
70 + 'custom_fields',
71 + 'created_at',
49 72 ];
50 73
51 74 protected $searchable = [
52 75 'display_name',
53 - 'username'
76 + 'username',
54 77 ];
55 78
56 - protected $appends = ['badge'];
79 + protected $appends = [ 'badge', 'permalink' ];
57 80
58 81 public function scopeSearchBy($query, $search)
59 82 {
60 83 if ($search) {
61 84 $fields = $this->searchable;
62 - $query->where(function ($query) use ($fields, $search) {
63 - $query->where(array_shift($fields), 'LIKE', "%$search%");
85 +
86 + $query->where(function ($q) use ($fields, $search) {
87 + $q->where(array_shift($fields), 'LIKE', "%$search%");
64 88 foreach ($fields as $field) {
65 - $query->orWhere($field, 'LIKE', "%$search%");
89 + $q->orWhere($field, 'LIKE', "%$search%");
66 90 }
67 91 });
68 92 }
69 93
@@ -72,11 +96,11 @@
72 96
73 97 public function scopeMentionBy($query, $search)
74 98 {
75 99 if ($search) {
76 - $query->where(function ($query) use ($search) {
77 - $query->where('display_name', 'LIKE', "$search%")
78 - ->orWhere('username', 'LIKE', "$search%");
100 + $query->where(function ($q) use ($search) {
101 + $q->where('display_name', 'LIKE', "%$search%")
102 + ->orWhere('username', 'LIKE', "%$search%");
79 103 });
80 104 }
81 105
82 106 return $query;
@@ -94,11 +118,44 @@
94 118
95 119 public function spaces()
96 120 {
97 121 return $this->belongsToMany(BaseSpace::class, 'fcom_space_user', 'user_id', 'space_id')
98 - ->withPivot(['role', 'created_at']);
122 + ->withPivot([ 'role', 'status', 'created_at' ]);
99 123 }
100 124
125 + public function posts()
126 + {
127 + return $this->hasMany(Feed::class, 'user_id', 'user_id');
128 + }
129 +
130 + // Relationship: Users this user follows
131 + public function follows()
132 + {
133 + return $this->hasMany(Follow::class, 'follower_id', 'user_id');
134 + }
135 +
136 + // Relationship: Users following this user
137 + public function followers()
138 + {
139 + return $this->hasMany(Follow::class, 'followed_id', 'user_id');
140 + }
141 +
142 + public function scheduledPosts()
143 + {
144 + return $this->posts()->where('status', 'scheduled')->where('scheduled_at', '!=', null);
145 + }
146 +
147 + public function comments()
148 + {
149 + return $this->hasMany(Comment::class, 'user_id', 'user_id');
150 + }
151 +
152 + public function courses()
153 + {
154 + return $this->belongsToMany(Course::class, 'fcom_space_user', 'user_id', 'space_id')
155 + ->withPivot([ 'role', 'status', 'created_at' ]);
156 + }
157 +
101 158 public function space_pivot()
102 159 {
103 160 return $this->belongsTo(SpaceUserPivot::class, 'user_id', 'user_id')->withoutGlobalScopes();
104 161 }
@@ -105,8 +162,9 @@
105 162
106 163 public function community_role()
107 164 {
108 165 return $this->belongsTo(Meta::class, 'user_id', 'object_id')
166 + ->where('object_type', 'user')
109 167 ->where('meta_key', '_user_community_roles');
110 168 }
111 169
112 170 /**
@@ -114,22 +172,75 @@
114 172 * @return string
115 173 */
116 174 public function getAvatarAttribute()
117 175 {
176 + $gravatarEnabled = Utility::getPrivacySetting('enable_gravatar') != 'no';
177 +
118 178 if (!empty($this->attributes['avatar'])) {
119 - return $this->attributes['avatar'];
179 + $url = $this->attributes['avatar'];
180 + if (!$gravatarEnabled && strpos($url, 'gravatar.com')) {
181 + $url = apply_filters('fluent_community/default_avatar', FLUENT_COMMUNITY_PLUGIN_URL . 'assets/images/placeholder.png', $this->user_id);
182 + }
183 +
184 + if (!$url) {
185 + $url = FLUENT_COMMUNITY_PLUGIN_URL . 'assets/images/placeholder.png';
186 + }
187 +
188 + return $url;
120 189 }
121 190
122 - return Utility::getFromCache('user_avatar_' . $this->user_id, function () {
123 - return $this->user ? $this->user->photo : 'https://ui-avatars.com/api/?name=' . $this->display_name . '/128';
191 + if (!$gravatarEnabled) {
192 + $url = apply_filters('fluent_community/default_avatar', FLUENT_COMMUNITY_PLUGIN_URL . 'assets/images/placeholder.png', $this->user_id);
193 +
194 + if (!$url) {
195 + $url = FLUENT_COMMUNITY_PLUGIN_URL . 'assets/images/placeholder.png';
196 + }
197 +
198 + return $url;
199 + }
200 +
201 + $url = Utility::getFromCache('user_avatar_' . $this->user_id, function () {
202 + $displayName = $this->display_name;
203 +
204 + if ($displayName) {
205 + $names = explode(' ', $displayName);
206 + // take the first letter of each name
207 + $displayName = '';
208 + foreach ($names as $name) {
209 + $name = (string)$name;
210 + $firstLetter = mb_substr($name, 0, 1, 'UTF-8');
211 + $displayName .= $firstLetter . '+';
212 + }
213 + }
214 +
215 + return get_avatar_url($this->user_id, [
216 + 'size' => 128,
217 + 'default' => apply_filters('fluent_community/default_avatar', 'https://ui-avatars.com/api/' . esc_attr($displayName) . '/128', $this->user_id),
218 + ]);
124 219 }, WEEK_IN_SECONDS);
220 +
221 + if (!$url) {
222 + $url = FLUENT_COMMUNITY_PLUGIN_URL . 'assets/images/placeholder.png';
223 + }
224 +
225 + return $url;
125 226 }
126 227
228 + public function hasCustomAvatar()
229 + {
230 + return !empty($this->attributes['avatar']);
231 + }
232 +
127 233 public function getBadgeAttribute()
128 234 {
129 235 return apply_filters('fluent_community/xprofile/badge', null, $this);
130 236 }
131 237
238 + public function getPermalinkAttribute()
239 + {
240 + return $this->getPermalink();
241 + }
242 +
132 243 public function getCrmContact()
133 244 {
134 245 if (!defined('FLUENTCRM')) {
135 246 return null;
@@ -146,17 +257,25 @@
146 257 }
147 258
148 259 public function getMetaAttribute($value)
149 260 {
150 - $settings = maybe_unserialize($value);
261 + $settings = Utility::safeUnserialize($value);
151 262
152 263 if (!$settings) {
153 264 $settings = [
154 265 'cover_photo' => '',
155 - 'website' => ''
266 + 'badge_slug' => [],
267 + 'website' => '',
156 268 ];
157 269 }
158 270
271 + if (!Utility::canViewUserProfile($this->user_id)) {
272 + return [
273 + 'cover_photo' => Arr::get($settings, 'cover_photo', ''),
274 + 'badge_slug' => Arr::get($settings, 'badge_slug', []),
275 + ];
276 + }
277 +
159 278 return $settings;
160 279 }
161 280
162 281 public function setMetaAttribute($value)
@@ -163,9 +282,9 @@
163 282 {
164 283 if (!$value) {
165 284 $value = [
166 285 'cover_photo' => '',
167 - 'website' => ''
286 + 'website' => '',
168 287 ];
169 288 }
170 289
171 290 $this->attributes['meta'] = maybe_serialize($value);
@@ -170,8 +289,24 @@
170 289
171 290 $this->attributes['meta'] = maybe_serialize($value);
172 291 }
173 292
293 + public function getCustomFieldsAttribute($value)
294 + {
295 + if (!$value) {
296 + return [];
297 + }
298 +
299 + $data = json_decode($value, true);
300 +
301 + return is_array($data) ? $data : [];
302 + }
303 +
304 + public function setCustomFieldsAttribute($value)
305 + {
306 + $this->attributes['custom_fields'] = is_array($value) ? json_encode($value) : $value;
307 + }
308 +
174 309 public function getFirstName()
175 310 {
176 311 if (!$this->display_name) {
177 312 return '';
@@ -206,9 +341,9 @@
206 341 'website' => 30,
207 342 'cover_photo' => 20,
208 343 'avatar' => 20,
209 344 'short_description' => 30,
210 - 'social_links' => 20
345 + 'social_links' => 20,
211 346 ];
212 347
213 348 $score = 0;
214 349
@@ -247,5 +382,19 @@
247 382
248 383 return $score > 100 ? 100 : $score;
249 384 }
250 385
386 + public function getPermalink()
387 + {
388 + return Helper::baseUrl('u/' . $this->username);
389 + }
390 +
391 + public function getJsRoute()
392 + {
393 + return [
394 + 'name' => 'user_profile',
395 + 'params' => [
396 + 'username' => $this->username,
397 + ],
398 + ];
399 + }
251 400 }