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.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 1.1.0 All 77 releases
fluent-community / app / Models / XProfile.php

XProfile.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.10.0, at app/Models/XProfile.php

401 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\App\Models;
4
5
6 use FluentCommunity\App\Functions\Utility;
7 use FluentCommunity\App\Models\Contact;
8 use FluentCommunity\App\Models\Feed;
9 use FluentCommunity\App\Models\User;
10 use FluentCommunity\App\Services\Helper;
11 use FluentCommunity\Framework\Support\Arr;
12 use FluentCommunity\Modules\Course\Model\Course;
13 use FluentCommunityPro\App\Models\Follow;
14 use FluentCrm\App\Models\Subscriber;
15
16 /**
17 * FluentCommunity XProfile Model
18 *
19 * Database Model
20 *
21 * @package FluentCommunity\App\Models
22 *
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
44 */
45 class XProfile extends Model
46 {
47 protected $table = 'fcom_xprofile';
48
49 protected $guarded = [ 'id' ];
50
51 protected $primaryKey = 'user_id';
52
53 protected $casts = [
54 'user_id' => 'integer',
55 'total_points' => 'integer',
56 'is_verified' => 'integer',
57 ];
58
59 protected $fillable = [
60 'user_id',
61 'total_points',
62 'username',
63 'status',
64 'is_verified',
65 'display_name',
66 'avatar',
67 'short_description',
68 'last_activity',
69 'meta',
70 'custom_fields',
71 'created_at',
72 ];
73
74 protected $searchable = [
75 'display_name',
76 'username',
77 ];
78
79 protected $appends = [ 'badge', 'permalink' ];
80
81 public function scopeSearchBy($query, $search)
82 {
83 if ($search) {
84 $fields = $this->searchable;
85
86 $query->where(function ($q) use ($fields, $search) {
87 $q->where(array_shift($fields), 'LIKE', "%$search%");
88 foreach ($fields as $field) {
89 $q->orWhere($field, 'LIKE', "%$search%");
90 }
91 });
92 }
93
94 return $query;
95 }
96
97 public function scopeMentionBy($query, $search)
98 {
99 if ($search) {
100 $query->where(function ($q) use ($search) {
101 $q->where('display_name', 'LIKE', "%$search%")
102 ->orWhere('username', 'LIKE', "%$search%");
103 });
104 }
105
106 return $query;
107 }
108
109 public function user()
110 {
111 return $this->belongsTo(User::class, 'user_id', 'ID');
112 }
113
114 public function contact()
115 {
116 return $this->hasOne(Contact::class, 'user_id', 'user_id');
117 }
118
119 public function spaces()
120 {
121 return $this->belongsToMany(BaseSpace::class, 'fcom_space_user', 'user_id', 'space_id')
122 ->withPivot([ 'role', 'status', 'created_at' ]);
123 }
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
158 public function space_pivot()
159 {
160 return $this->belongsTo(SpaceUserPivot::class, 'user_id', 'user_id')->withoutGlobalScopes();
161 }
162
163 public function community_role()
164 {
165 return $this->belongsTo(Meta::class, 'user_id', 'object_id')
166 ->where('object_type', 'user')
167 ->where('meta_key', '_user_community_roles');
168 }
169
170 /**
171 * Accessor to get dynamic photo attribute
172 * @return string
173 */
174 public function getAvatarAttribute()
175 {
176 $gravatarEnabled = Utility::getPrivacySetting('enable_gravatar') != 'no';
177
178 if (!empty($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;
189 }
190
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 ]);
219 }, WEEK_IN_SECONDS);
220
221 if (!$url) {
222 $url = FLUENT_COMMUNITY_PLUGIN_URL . 'assets/images/placeholder.png';
223 }
224
225 return $url;
226 }
227
228 public function hasCustomAvatar()
229 {
230 return !empty($this->attributes['avatar']);
231 }
232
233 public function getBadgeAttribute()
234 {
235 return apply_filters('fluent_community/xprofile/badge', null, $this);
236 }
237
238 public function getPermalinkAttribute()
239 {
240 return $this->getPermalink();
241 }
242
243 public function getCrmContact()
244 {
245 if (!defined('FLUENTCRM')) {
246 return null;
247 }
248
249 if ($this->user_email) {
250 return Subscriber::where('user_id', $this->ID)
251 ->orWhere('email', $this->user_email)
252 ->first();
253 }
254
255 return Subscriber::where('user_id', $this->ID)
256 ->first();
257 }
258
259 public function getMetaAttribute($value)
260 {
261 $settings = Utility::safeUnserialize($value);
262
263 if (!$settings) {
264 $settings = [
265 'cover_photo' => '',
266 'badge_slug' => [],
267 'website' => '',
268 ];
269 }
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
278 return $settings;
279 }
280
281 public function setMetaAttribute($value)
282 {
283 if (!$value) {
284 $value = [
285 'cover_photo' => '',
286 'website' => '',
287 ];
288 }
289
290 $this->attributes['meta'] = maybe_serialize($value);
291 }
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
309 public function getFirstName()
310 {
311 if (!$this->display_name) {
312 return '';
313 }
314 $fullName = explode(' ', $this->display_name);
315 return $fullName[0];
316 }
317
318 public function getLastName()
319 {
320
321 if (!$this->display_name) {
322 return '';
323 }
324
325 $fullName = explode(' ', $this->display_name);
326
327 // remove the first name
328 array_shift($fullName);
329
330 if (count($fullName) == 0) {
331 return '';
332 }
333 return implode(' ', $fullName);
334 }
335
336 public function getCompletionScore()
337 {
338 $scores = [
339 'first_name' => 20,
340 'last_name' => 20,
341 'website' => 30,
342 'cover_photo' => 20,
343 'avatar' => 20,
344 'short_description' => 30,
345 'social_links' => 20,
346 ];
347
348 $score = 0;
349
350 if ($this->getFirstName()) {
351 $score += $scores['first_name'];
352 }
353
354 if ($this->getLastName()) {
355 $score += $scores['last_name'];
356 }
357
358 $meta = $this->meta;
359 if (Arr::get($meta, 'website')) {
360 $score += $scores['website'];
361 }
362
363 if (Arr::get($meta, 'cover_photo')) {
364 $score += $scores['cover_photo'];
365 }
366
367 if ($this->short_description) {
368 $score += $scores['short_description'];
369 }
370
371 if ($score >= 100) {
372 return 100;
373 }
374
375 if (!empty($meta['social_links']) && array_filter(Arr::get($meta, 'social_links', []))) {
376 $score += $scores['social_links'];
377 }
378
379 if (!empty($this->attributes['avatar'])) {
380 $score += $scores['avatar'];
381 }
382
383 return $score > 100 ? 100 : $score;
384 }
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 }
400 }
401