PluginProbe ʕ •ᴥ•ʔ
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress / 4.17.3
Paid Membership Plugin, Ecommerce, User Registration Form, Login Form, User Profile & Restrict Content – ProfilePress v4.17.3
4.17.3 4.17.2 4.17.1 4.17.0 4.16.19 4.16.18 4.16.17 4.16.16 trunk 1.0 1.0.1 1.0.2 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5a 1.1.6 1.1.7 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.4 1.4.1 1.4.2 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.7 1.7.1 1.7.2 1.8 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.1.9 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.2 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0 3.1 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.16 3.1.17 3.1.18 3.1.19 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.13.3 4.13.4 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.15.0 4.15.1 4.15.10 4.15.11 4.15.12 4.15.13 4.15.14 4.15.15 4.15.16 4.15.17 4.15.18 4.15.19 4.15.2 4.15.20 4.15.20.1 4.15.21 4.15.22 4.15.23 4.15.24 4.15.25 4.15.3 4.15.4 4.15.5 4.15.6 4.15.7 4.15.8 4.15.9 4.16.0 4.16.1 4.16.10 4.16.11 4.16.12 4.16.13 4.16.14 4.16.15 4.16.2 4.16.3 4.16.4 4.16.5 4.16.6 4.16.7 4.16.8 4.16.9 4.2.0 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.7.0 4.8.0 4.9.0
wp-user-avatar / src / ShortcodeParser / Builder / FrontendProfileBuilder.php
wp-user-avatar / src / ShortcodeParser / Builder Last commit date
EditProfileBuilder.php 3 years ago FieldsShortcodeCallback.php 6 months ago FrontendProfileBuilder.php 1 day ago GlobalShortcodes.php 3 years ago LoginFormBuilder.php 2 years ago PasswordResetBuilder.php 3 months ago RegistrationFormBuilder.php 1 year ago index.php 5 years ago
FrontendProfileBuilder.php
728 lines
1 <?php
2
3 namespace ProfilePress\Core\ShortcodeParser\Builder;
4
5 use ProfilePress\Core\Classes\ExtensionManager as EM;
6 use ProfilePress\Core\Classes\PROFILEPRESS_sql;
7 use WP_User;
8
9 class FrontendProfileBuilder
10 {
11 private static WP_User $user_data;
12
13 /**
14 * Define all front-end profile sub-shortcode.
15 *
16 * @param $user
17 */
18 public function __construct($user)
19 {
20 self::$user_data = $user;
21
22 add_shortcode('profile-username', array($this, 'profile_username'));
23
24 add_shortcode('profile-email', array($this, 'profile_email'));
25
26 add_shortcode('profile-website', array($this, 'profile_website'));
27
28 add_shortcode('profile-nickname', array($this, 'profile_nickname'));
29
30 add_shortcode('profile-display-name', array($this, 'profile_display_name'));
31
32 add_shortcode('profile-first-name', array($this, 'profile_first_name'));
33
34 add_shortcode('profile-last-name', array($this, 'profile_last_name'));
35
36 add_shortcode('profile-bio', array($this, 'profile_bio'));
37
38 add_shortcode('profile-cpf', array($this, 'profile_custom_profile_field'));
39 add_shortcode('profile-file', array($this, 'profile_user_uploaded_file'));
40
41 add_shortcode('profile-cover-image-url', array($this, 'cover_image_url'));
42
43 add_shortcode('profile-avatar-url', array($this, 'user_avatar_url'));
44 add_shortcode('user-avatar-url', array($this, 'user_avatar_url')); // backward compat
45
46 add_shortcode('profile-hide-empty-data', array($this, 'hide_empty_data'));
47
48 add_shortcode('post-count', array($this, 'post_count'));
49 add_shortcode('profile-post-count', array($this, 'post_count'));
50
51 add_shortcode('comment-count', array($this, 'get_comment_count'));
52 add_shortcode('profile-comment-count', array($this, 'get_comment_count'));
53
54 add_shortcode('profile-post-list', array($this, 'author_post_list'));
55 add_shortcode('profile-comment-list', array($this, 'author_comment_list'));
56
57 add_shortcode('profile-view-url', array($this, 'view_user_profile_url'));
58
59 add_shortcode('profile-author-posts-url', array($this, 'author_post_url'));
60
61 add_shortcode('profile-date-registered', array($this, 'date_user_registered'));
62
63 add_shortcode('jcarousel-author-posts', array($this, 'pp_jcarousel_author_posts'));
64
65 /**
66 * @param object $user WP_User object
67 */
68 do_action('ppress_register_profile_shortcode', $user);
69 }
70
71 public function date_user_registered()
72 {
73 return date('F jS, Y', strtotime(self::$user_data->user_registered));
74 }
75
76 public function view_user_profile_url(): string
77 {
78 return ppress_get_frontend_profile_url(self::$user_data->user_login);
79 }
80
81 public function author_post_url()
82 {
83 return get_author_posts_url(self::$user_data->ID);
84 }
85
86 public static function author_posts_query($user_id, $attributes)
87 {
88 $attributes = shortcode_atts(array('limit' => 10, 'offset' => 0), $attributes);
89
90 $limit = absint($attributes['limit']);
91 $offset = absint($attributes['offset']);
92
93 $posts = get_posts(
94 apply_filters('ppress_frontend_profile_author_post_list_args', [
95 'author' => $user_id,
96 'posts_per_page' => $limit,
97 'offset' => $offset
98 ], $user_id, $attributes)
99 );
100
101 $output = '';
102
103 if ( ! empty($posts)) {
104
105 $output .= "<ul class='pp-user-post-list'>";
106 /** @var \WP_Post $post */
107 foreach ($posts as $post) {
108 $output .= sprintf(
109 '<li class="pp-user-post-item"><a href="%s"><h3 class="pp-post-item-head">%s</h3></a></li>',
110 get_permalink($post->ID),
111 $post->post_title,
112 apply_filters('ppress_author_post_after_title', '', $post, $user_id, $attributes)
113 );
114 }
115
116 $output .= "</ul>";
117
118 } else {
119
120 $note = esc_html__('This user has not created any post.', 'wp-user-avatar');
121
122 if (self::$user_data->ID == get_current_user_id()) {
123 $note = esc_html__('You have not created any post.', 'wp-user-avatar');
124 }
125
126 $output .= sprintf('<div class="pp-user-comment-no-item"><span>%s</span></div>', $note);
127 }
128
129 return [
130 'structure' => $output,
131 'total_post_count' => is_array($posts) ? count($posts) : 0
132 ];
133 }
134
135 public function author_post_list($attributes)
136 {
137 $result = self::author_posts_query(self::$user_data->ID, $attributes);
138
139 return $result['structure'];
140 }
141
142 public static function author_comment_query($user_id, $attributes)
143 {
144 $attributes = shortcode_atts(array('limit' => 10, 'offset' => 0), $attributes);
145
146 $limit = absint($attributes['limit']);
147 $offset = absint($attributes['offset']);
148
149 $comments = get_comments([
150 'number' => $limit,
151 'user_id' => $user_id,
152 'post_status' => ['publish'],
153 'status' => 'approve',
154 'offset' => $offset
155 ]);
156
157 $output = '';
158
159 if ( ! empty($comments)) {
160
161 $output .= '<div class="pp-user-comment-list">';
162 /** @var \WP_Comment $comment */
163 foreach ($comments as $comment) {
164 $output .= '<div class="pp-user-comment-item">';
165 $output .= '<div class="pp-user-comment-item-link">';
166 $output .= sprintf(
167 '<a href="%s">%s</a>',
168 esc_url(get_comment_link($comment->comment_ID)),
169 get_comment_excerpt($comment->comment_ID)
170 );
171 $output .= '</div>';
172 $output .= '<div class="pp-user-comment-item-meta">';
173 $output .= sprintf('On <a href="%s">%s</a>', get_permalink($comment->comment_post_ID), get_the_title($comment->comment_post_ID));
174 $output .= '</div>';
175 $output .= '</div>';
176 }
177
178 $output .= "</div>";
179
180 } else {
181
182 $note = esc_html__('This user has not made any comment.', 'wp-user-avatar');
183
184 if (self::$user_data->ID == get_current_user_id()) {
185 $note = esc_html__('You have not made any comment.', 'wp-user-avatar');
186 }
187
188 $output .= sprintf('<div class="pp-user-comment-no-item"><span>%s</span></div>', $note);
189 }
190
191 return [
192 'structure' => $output,
193 'comment_count' => is_array($comments) ? count($comments) : 0
194 ];
195 }
196
197 public function author_comment_list($attributes)
198 {
199 $result = self::author_comment_query(self::$user_data->ID, $attributes);
200
201 return $result['structure'];
202 }
203
204 /**
205 * Profile username
206 *
207 * @return mixed
208 */
209 public function profile_username()
210 {
211 $capitalization = apply_filters('ppress_capitalize_username', true);
212
213 $username = self::$user_data->user_login;
214
215 $username = $capitalization ? ucwords($username) : $username;
216
217 return apply_filters('ppress_profile_username', $username, self::$user_data);
218 }
219
220
221 /**
222 * User email
223 *
224 * @return mixed
225 */
226 public function profile_email()
227 {
228 return apply_filters('ppress_profile_email', self::$user_data->user_email, self::$user_data);
229 }
230
231 /**
232 * Return the user avatar image URL
233 *
234 * @param array $atts Shortcode attributes
235 *
236 * @return string image url
237 */
238 public function user_avatar_url($atts)
239 {
240 $user_id = self::$user_data->ID;
241
242 $args = ['ppress-full' => true];
243
244 if ( ! empty($atts['size'])) $args['size'] = absint($atts['size']);
245
246 return apply_filters('ppress_profile_avatar_url', get_avatar_url($user_id, $args), self::$user_data);
247 }
248
249 /**
250 * Return user cover photo url
251 *
252 * @return string image url
253 */
254 public function cover_image_url()
255 {
256 $user_id = self::$user_data->ID;
257
258 return apply_filters('ppress_cover_image_url', ppress_get_cover_image_url($user_id), self::$user_data);
259 }
260
261 /**
262 * User website URL
263 *
264 * @return mixed
265 */
266 public function profile_website()
267 {
268 return apply_filters('ppress_profile_website', esc_url(self::$user_data->user_url), self::$user_data);
269 }
270
271 /**
272 * Nickname of user
273 *
274 * @return mixed
275 */
276 public function profile_nickname()
277 {
278 return apply_filters('ppress_profile_nickname', ucwords(ppress_strip_shortcodes(self::$user_data->nickname)), self::$user_data);
279 }
280
281 /**
282 * Display name of profile
283 *
284 * @return mixed
285 */
286 public function profile_display_name($atts = false)
287 {
288 $display_name = ppress_strip_shortcodes(self::$user_data->display_name);
289
290 if ( ! empty($atts['format']) && ! empty(self::$user_data->first_name) && ! empty(self::$user_data->last_name)) {
291
292 switch ($atts['format']) {
293 case 'first_last_names':
294 $display_name = ppress_strip_shortcodes(self::$user_data->first_name) . ' ' . ppress_strip_shortcodes(self::$user_data->last_name);
295 break;
296 case 'last_first_names':
297 $display_name = ppress_strip_shortcodes(self::$user_data->last_name) . ' ' . ppress_strip_shortcodes(self::$user_data->first_name);
298 break;
299 case 'first_name_initial_l':
300 $display_name = ppress_strip_shortcodes(self::$user_data->first_name) . ' ' . ppress_strip_shortcodes(self::$user_data->last_name[0]);
301 break;
302 case 'f_initial_last_name':
303 $display_name = ppress_strip_shortcodes(self::$user_data->first_name[0]) . ' ' . ppress_strip_shortcodes(self::$user_data->last_name);
304 break;
305 }
306 }
307
308 return apply_filters('ppress_profile_display_name', $display_name, self::$user_data);
309 }
310
311 /**
312 * Profile first name
313 *
314 * @return mixed
315 */
316 public function profile_first_name()
317 {
318 return apply_filters('ppress_profile_first_name', ucwords(ppress_strip_shortcodes(self::$user_data->first_name)), self::$user_data);
319 }
320
321
322 /**
323 * Last name of user.
324 *
325 * @return mixed
326 */
327 public function profile_last_name()
328 {
329 return apply_filters('ppress_profile_last_name', ucwords(ppress_strip_shortcodes(self::$user_data->last_name)), self::$user_data);
330 }
331
332 /**
333 * Description/bio of user.
334 *
335 * @return mixed
336 */
337 public function profile_bio()
338 {
339 return apply_filters(
340 'ppress_profile_bio',
341 make_clickable(wpautop(wp_kses_post(ppress_strip_shortcodes(html_entity_decode(self::$user_data->description))))),
342 self::$user_data
343 );
344 }
345
346 /**
347 * Custom profile data of user.
348 *
349 * @param $atts array shortcode attributes
350 *
351 * @return string
352 */
353 public function profile_custom_profile_field($atts)
354 {
355 if ( ! EM::is_enabled(EM::CUSTOM_FIELDS)) return '';
356
357 $atts = shortcode_atts(
358 array(
359 'key' => '',
360 'default' => '',
361 ),
362 $atts
363 );
364
365 $key = esc_attr($atts['key']);
366
367 if (empty($key)) return esc_html__('Field key is missing', 'wp-user-avatar');
368
369 $type = PROFILEPRESS_sql::get_field_type($key);
370
371 if ('file' == $type) {
372 return $this->profile_user_uploaded_file($atts);
373 }
374
375 $data = self::$user_data->{$key};
376
377 if (is_array($data)) {
378 $data = implode(', ',
379 array_filter($data, function ($val) {
380 return ! empty($val);
381 })
382 );
383 }
384
385 if (empty($data) && ! ppress_is_boolean($data) && ! empty($atts['default'])) {
386 $data = esc_attr($atts['default']);
387 }
388
389 $data = ppress_strip_shortcodes($data);
390
391 if (is_string($data)) {
392 $data = in_array($key, array_keys(ppress_social_network_fields()), true) ? esc_url($data) : esc_html($data);
393 }
394
395 return apply_filters('ppress_profile_cpf', $data, self::$user_data);
396 }
397
398 public static function get_user_uploaded_file($user_id, $field_key, $is_raw = false)
399 {
400 $user_upload_data = get_user_meta($user_id, 'pp_uploaded_files', true);
401
402 if (empty($user_upload_data)) return '';
403
404 $filename = $user_upload_data[$field_key] ?? '';
405
406 if (empty($filename)) return '';
407
408 $link = PPRESS_FILE_UPLOAD_URL . $filename;
409
410 return $is_raw === true || $is_raw == 'true' ? $link : "<a href='$link'>$filename</a>";
411 }
412
413 public function profile_user_uploaded_file($atts)
414 {
415 $atts = ppress_normalize_attributes($atts);
416
417 $atts = shortcode_atts(['key' => '', 'raw' => false], $atts);
418
419 $return = self::get_user_uploaded_file(self::$user_data->ID, esc_attr($atts['key']), $atts['raw']);
420
421 return apply_filters('ppress_profile_file', $return, self::$user_data);
422 }
423
424 /**
425 * Return number of post written by a user
426 *
427 * @return int
428 */
429 public function post_count()
430 {
431 return apply_filters('ppress_profile_post_count', count_user_posts(self::$user_data->ID), self::$user_data, true);
432 }
433
434 public function hide_empty_data($atts, $content)
435 {
436 $atts = shortcode_atts(
437 array(
438 'field' => '',
439 'default' => ''
440 ),
441 $atts
442 );
443
444 $key = ! empty($atts['field']) ? strip_tags($atts['field']) : '';
445
446 switch ($key) {
447 case 'username':
448 $key = 'user_login';
449 break;
450 case 'email':
451 $key = 'user_email';
452 break;
453 case 'website':
454 $key = 'user_url';
455 break;
456 case 'nickname':
457 $key = 'nickname';
458 break;
459 case 'display_name':
460 $key = 'display_name';
461 break;
462 case 'first_name':
463 $key = 'first_name';
464 break;
465 case 'last_name':
466 $key = 'last_name';
467 break;
468 case 'bio':
469 $key = 'description';
470 break;
471 }
472
473 if ( ! empty($key) && ! empty(self::$user_data->$key)) {
474 return do_shortcode($content);
475 }
476
477 return ppress_var($atts, 'default', '', true);
478 }
479
480 /**
481 * Return the total comment count made by a user
482 */
483 public function get_comment_count()
484 {
485 global $wpdb;
486 $userId = absint(self::$user_data->ID);
487
488 $count = $wpdb->get_var(
489 $wpdb->prepare(
490 "SELECT COUNT(comment_ID) FROM {$wpdb->comments} WHERE user_id = %d AND comment_type = '' AND comment_approved = '1'",
491 $userId
492 )
493 );
494
495 return apply_filters('ppress_profile_comment_count', $count, self::$user_data);
496 }
497
498 protected function jcarousel_css()
499 {
500 ob_start();
501 ?>
502 <style type="text/css">
503 /* jcarousel responsive */
504 a.jcarousel-control-next, a.jcarousel-control-prev {
505 text-decoration: none !important;
506 }
507
508 .pp-jcarousel-wrapper ul li a {
509 color: #5B5B5B;
510 text-decoration: none
511 }
512
513 .pp-jcarousel-wrapper {
514 color: #5B5B5B;
515 background-color: #F5F5F5;
516 margin: 20px auto;
517 position: relative;
518 border: 10px solid #fff;
519 -webkit-border-radius: 5px;
520 -moz-border-radius: 5px;
521 border-radius: 5px;
522 -webkit-box-shadow: 0 0 2px #999;
523 -moz-box-shadow: 0 0 2px #999;
524 box-shadow: 0 0 2px #999;
525 }
526
527 /** Carousel **/
528 .ppjcarousel {
529 position: relative;
530 overflow: hidden;
531 width: 100%;
532 }
533
534 .ppjcarousel ul {
535 width: 20000em;
536 position: relative;
537 list-style: none;
538 margin: 0;
539 padding: 0;
540 }
541
542 .ppjcarousel li {
543 width: 200px;
544 float: left;
545 margin: 1px 3px 1px 0;
546 -moz-box-sizing: border-box;
547 -webkit-box-sizing: border-box;
548 box-sizing: border-box;
549 }
550
551 .ppjcarousel img {
552 display: block;
553 width: 100%;
554 height: 100px !important;
555 }
556
557 .jc-no-post {
558 font-family: inherit;
559 font-size: 15px;
560 padding: 5px;
561 text-align: center;
562 }
563
564 .jc-title {
565 font-family: inherit;
566 font-size: 15px;
567 word-wrap: break-word;
568 padding: 5px;
569 margin: 0 4px;
570 text-align: center;
571 }
572
573 /** Carousel Controls **/
574 .jcarousel-control-prev, .jcarousel-control-next {
575 position: absolute;
576 top: 50%;
577 margin-top: -15px;
578 width: 30px;
579 height: 30px;
580 text-align: center;
581 background: #4E443C;
582 color: #fff;
583 text-decoration: none;
584 text-shadow: 0 0 1px #000;
585 font: 24px/27px Arial, sans-serif;
586 -webkit-border-radius: 30px;
587 -moz-border-radius: 30px;
588 border-radius: 30px;
589 -webkit-box-shadow: 0 0 4px #F0EFE7;
590 -moz-box-shadow: 0 0 4px #F0EFE7;
591 box-shadow: 0 0 4px #F0EFE7;
592 }
593
594 .jcarousel-control-prev {
595 left: 15px;
596 }
597
598 .jcarousel-control-next {
599 right: 15px;
600 }
601
602 /** Carousel Pagination **/
603 .jcarousel-pagination {
604 position: absolute;
605 bottom: -40px;
606 left: 50%;
607 -webkit-transform: translate(-50%, 0);
608 -ms-transform: translate(-50%, 0);
609 -moz-transform: translate(-50%, 0);
610 transform: translate(-50%, 0);
611 margin: 0;
612 }
613
614 .jcarousel-pagination a {
615 text-decoration: none;
616 display: inline-block;
617 font-size: 11px;
618 height: 10px;
619 width: 10px;
620 line-height: 10px;
621 background: #fff;
622 color: #4E443C;
623 border-radius: 10px;
624 text-indent: -9999px;
625 margin-right: 7px;
626 -webkit-box-shadow: 0 0 2px #4E443C;
627 -moz-box-shadow: 0 0 2px #4E443C;
628 box-shadow: 0 0 2px #4E443C;
629 }
630
631 .jcarousel-pagination a.active {
632 background: #4E443C;
633 color: #fff;
634 opacity: 1;
635 -webkit-box-shadow: 0 0 2px #F0EFE7;
636 -moz-box-shadow: 0 0 2px #F0EFE7;
637 box-shadow: 0 0 2px #F0EFE7;
638 }
639 </style>
640 <?php
641 return ppress_minify_css(ob_get_clean());
642 }
643
644 /**
645 * jCarousel author latest post slider
646 *
647 * @param $atts
648 *
649 * @return string
650 */
651 public function pp_jcarousel_author_posts($atts)
652 {
653 wp_enqueue_script('pp-jcarousel', PPRESS_ASSETS_URL . '/js/jcarousel.min.js', array('jquery'), PPRESS_VERSION_NUMBER, true);
654
655 $atts = shortcode_atts(
656 array(
657 'count' => 10,
658 'default' => PPRESS_ASSETS_URL . '/images/frontend/jc_dft_img.jpg',
659 'width' => '',
660 ),
661 $atts
662 );
663
664 $posts = get_posts(
665 array(
666 'post_type' => 'post',
667 'posts_per_page' => (int)$atts['count'],
668 'author' => self::$user_data->ID,
669 )
670 );
671
672 $default_img = esc_url($atts['default']);
673 $width = ! empty($atts['width']) ? ' style="width: ' . esc_attr($atts['width']) . ';"' : null;
674
675 ob_start();
676 echo $this->jcarousel_css();
677 ?>
678 <div class="pp-jcarousel-wrapper"<?php echo $width; ?>>
679 <div class="ppjcarousel">
680 <?php
681 if (empty($posts)) {
682 echo '<div class="jc-no-post">' . apply_filters('jcarousel_no_post', esc_html__('No post written yet.', 'wp-user-avatar')) . '</div>';
683 } else {
684
685 echo '<ul>';
686 foreach ($posts as $post) {
687 $feature_img = wp_get_attachment_image_src(get_post_thumbnail_id($post->ID), 'medium', false);
688
689 $feature_img = isset($feature_img[0]) ? $feature_img[0] : false;
690
691 if ( ! $feature_img) {
692 $feature_img = $default_img;
693 }
694 ?>
695 <li>
696 <a href="<?php echo get_permalink($post->ID); ?>">
697 <img src="<?php echo esc_url($feature_img); ?>" alt="<?php esc_attr_e($post->post_title); ?>">
698
699 <div class="jc-title"><?php esc_html_e($post->post_title); ?></div>
700 </a>
701 </li>
702 <?php
703 }
704 echo '</ul>';
705 }
706 ?>
707 </div>
708
709 <?php
710 // hide jcarousel nav link if no post is found
711 if ( ! empty($posts)) { ?>
712 <a href="#" class="jcarousel-control-prev">&lsaquo;</a>
713 <a href="#" class="jcarousel-control-next">&rsaquo;</a>
714 <p class="jcarousel-pagination"></p>
715 <?php } ?>
716 </div>
717 <?php
718 return apply_filters('ppress_jcarousel_author_posts', ob_get_clean(), self::$user_data);
719 }
720
721 public static function get_instance($user = '')
722 {
723 $user = ! empty($user) ? $user : wp_get_current_user();
724
725 return new self($user);
726 }
727 }
728