PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.44
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.44
51.1.87 51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 All 41 releases
king-addons / includes / widgets / TB_Post_Meta / TB_Post_Meta.php

TB_Post_Meta.php in King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder 51.1.44, at includes/widgets/TB_Post_Meta/TB_Post_Meta.php

506 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Theme Builder Post Meta widget (Free).
4 *
5 * @package King_Addons
6 */
7
8 namespace King_Addons;
9
10 use Elementor\Controls_Manager;
11 use Elementor\Group_Control_Typography;
12 use Elementor\Repeater;
13 use Elementor\Widget_Base;
14
15 if (!defined('ABSPATH')) {
16 exit;
17 }
18
19 /**
20 * Displays post meta items such as date, author, categories, and comments.
21 */
22 class TB_Post_Meta extends Widget_Base
23 {
24 /**
25 * Widget slug.
26 *
27 * @return string
28 */
29 public function get_name(): string
30 {
31 return 'king-addons-tb-post-meta';
32 }
33
34 /**
35 * Widget title.
36 *
37 * @return string
38 */
39 public function get_title(): string
40 {
41 return esc_html__('TB - Post Meta', 'king-addons');
42 }
43
44 /**
45 * Widget icon.
46 *
47 * @return string
48 */
49 public function get_icon(): string
50 {
51 return 'eicon-meta-data';
52 }
53
54 /**
55 * Style dependencies.
56 *
57 * @return array<int, string>
58 */
59 public function get_style_depends(): array
60 {
61 return [KING_ADDONS_ASSETS_UNIQUE_KEY . '-tb-post-meta-style'];
62 }
63
64 /**
65 * Script dependencies.
66 *
67 * @return array<int, string>
68 */
69 public function get_script_depends(): array
70 {
71 return [KING_ADDONS_ASSETS_UNIQUE_KEY . '-tb-post-meta-script'];
72 }
73
74 /**
75 * Categories.
76 *
77 * @return array<int, string>
78 */
79 public function get_categories(): array
80 {
81 return ['king-addons'];
82 }
83
84 /**
85 * Keywords.
86 *
87 * @return array<int, string>
88 */
89 public function get_keywords(): array
90 {
91 return ['meta', 'author', 'date', 'categories', 'tags', 'king-addons'];
92 }
93
94 /**
95 * Register controls.
96 *
97 * @return void
98 */
99 public function register_controls(): void
100 {
101 $this->register_content_controls(false);
102 $this->register_style_controls(false);
103 $this->register_pro_notice_controls();
104 }
105
106 /**
107 * Render widget output.
108 *
109 * @return void
110 */
111 public function render(): void
112 {
113 $settings = $this->get_settings_for_display();
114 $this->render_output($settings, false);
115 }
116
117 /**
118 * Content controls.
119 *
120 * @param bool $is_pro Whether Pro controls are enabled.
121 *
122 * @return void
123 */
124 protected function register_content_controls(bool $is_pro): void
125 {
126 $repeater = new Repeater();
127 $repeater->add_control(
128 'kng_meta_type',
129 [
130 'label' => esc_html__('Meta Item', 'king-addons'),
131 'type' => Controls_Manager::SELECT,
132 'options' => [
133 'date' => esc_html__('Date', 'king-addons'),
134 'author' => esc_html__('Author', 'king-addons'),
135 'categories' => esc_html__('Categories', 'king-addons'),
136 'tags' => esc_html__('Tags', 'king-addons'),
137 'comments' => esc_html__('Comments Count', 'king-addons'),
138 'reading_time' => $is_pro ?
139 esc_html__('Reading Time', 'king-addons') :
140 sprintf(__('Reading Time %s', 'king-addons'), '<i class="eicon-pro-icon"></i>'),
141 ],
142 'default' => 'date',
143 ]
144 );
145
146 $this->start_controls_section(
147 'kng_content_section',
148 [
149 'label' => KING_ADDONS_ELEMENTOR_ICON . esc_html__('Content', 'king-addons'),
150 'tab' => Controls_Manager::TAB_CONTENT,
151 ]
152 );
153
154 $this->add_control(
155 'kng_layout',
156 [
157 'label' => esc_html__('Layout', 'king-addons'),
158 'type' => Controls_Manager::SELECT,
159 'default' => 'inline',
160 'options' => [
161 'inline' => esc_html__('Inline', 'king-addons'),
162 'stacked' => esc_html__('Stacked', 'king-addons'),
163 ],
164 ]
165 );
166
167 $this->add_control(
168 'kng_separator',
169 [
170 'label' => esc_html__('Separator', 'king-addons'),
171 'type' => Controls_Manager::TEXT,
172 'default' => '•',
173 'condition' => [
174 'kng_layout' => 'inline',
175 ],
176 ]
177 );
178
179 $this->add_control(
180 'kng_date_format',
181 [
182 'label' => esc_html__('Date Format', 'king-addons'),
183 'type' => Controls_Manager::SELECT,
184 'options' => [
185 'default' => esc_html__('Default', 'king-addons'),
186 'medium' => esc_html__('Medium', 'king-addons'),
187 'custom' => esc_html__('Custom', 'king-addons'),
188 ],
189 'default' => 'default',
190 ]
191 );
192
193 $this->add_control(
194 'kng_date_format_custom',
195 [
196 'label' => esc_html__('Custom Date Format', 'king-addons'),
197 'type' => Controls_Manager::TEXT,
198 'placeholder' => esc_html__('F j, Y', 'king-addons'),
199 'condition' => [
200 'kng_date_format' => 'custom',
201 ],
202 ]
203 );
204
205 $this->add_control(
206 'kng_author_link',
207 [
208 'label' => esc_html__('Link Author to Archive', 'king-addons'),
209 'type' => Controls_Manager::SWITCHER,
210 'return_value' => 'yes',
211 'default' => 'yes',
212 ]
213 );
214
215 $this->add_control(
216 'kng_terms_link',
217 [
218 'label' => esc_html__('Link Categories/Tags', 'king-addons'),
219 'type' => Controls_Manager::SWITCHER,
220 'return_value' => 'yes',
221 'default' => 'yes',
222 ]
223 );
224
225 $this->add_control(
226 'kng_meta_items',
227 [
228 'label' => esc_html__('Meta Items', 'king-addons'),
229 'type' => Controls_Manager::REPEATER,
230 'fields' => $repeater->get_controls(),
231 'title_field' => '{{{ kng_meta_type }}}',
232 'default' => [
233 ['kng_meta_type' => 'date'],
234 ['kng_meta_type' => 'author'],
235 ['kng_meta_type' => 'categories'],
236 ['kng_meta_type' => 'tags'],
237 ['kng_meta_type' => 'comments'],
238 ],
239 ]
240 );
241
242 $this->end_controls_section();
243 }
244
245 /**
246 * Style controls.
247 *
248 * @param bool $is_pro Whether Pro controls are enabled.
249 *
250 * @return void
251 */
252 protected function register_style_controls(bool $is_pro): void
253 {
254 $this->start_controls_section(
255 'kng_style_section',
256 [
257 'label' => esc_html__('Style', 'king-addons'),
258 'tab' => Controls_Manager::TAB_STYLE,
259 ]
260 );
261
262 $this->add_group_control(
263 Group_Control_Typography::get_type(),
264 [
265 'name' => 'kng_typography',
266 'selector' => '{{WRAPPER}} .king-addons-tb-post-meta, {{WRAPPER}} .king-addons-tb-post-meta a',
267 ]
268 );
269
270 $this->add_control(
271 'kng_text_color',
272 [
273 'label' => esc_html__('Text Color', 'king-addons'),
274 'type' => Controls_Manager::COLOR,
275 'selectors' => [
276 '{{WRAPPER}} .king-addons-tb-post-meta' => 'color: {{VALUE}};',
277 '{{WRAPPER}} .king-addons-tb-post-meta a' => 'color: {{VALUE}};',
278 ],
279 ]
280 );
281
282 $this->add_control(
283 'kng_text_color_hover',
284 [
285 'label' => esc_html__('Link Hover Color', 'king-addons'),
286 'type' => Controls_Manager::COLOR,
287 'selectors' => [
288 '{{WRAPPER}} .king-addons-tb-post-meta a:hover' => 'color: {{VALUE}};',
289 ],
290 ]
291 );
292
293 $this->add_responsive_control(
294 'kng_gap',
295 [
296 'label' => esc_html__('Gap', 'king-addons'),
297 'type' => Controls_Manager::SLIDER,
298 'size_units' => ['px'],
299 'range' => [
300 'px' => ['min' => 0, 'max' => 40],
301 ],
302 'default' => [
303 'size' => 8,
304 'unit' => 'px',
305 ],
306 'selectors' => [
307 '{{WRAPPER}} .king-addons-tb-post-meta' => '--kng-meta-gap: {{SIZE}}{{UNIT}};',
308 ],
309 ]
310 );
311
312 $this->end_controls_section();
313 }
314
315 /**
316 * Pro upsell section.
317 *
318 * @return void
319 */
320 protected function register_pro_notice_controls(): void
321 {
322 if (king_addons_freemius()->can_use_premium_code__premium_only()) {
323 return;
324 }
325
326 Core::renderProFeaturesSection(
327 $this,
328 '',
329 Controls_Manager::RAW_HTML,
330 'tb-post-meta',
331 [
332 'Reading time meta item',
333 'Icons and badge styles for taxonomies',
334 'Separate typography for labels and values',
335 ]
336 );
337 }
338
339 /**
340 * Render output helper.
341 *
342 * @param array<string, mixed> $settings Widget settings.
343 * @param bool $is_pro Whether Pro is enabled.
344 *
345 * @return void
346 */
347 protected function render_output(array $settings, bool $is_pro): void
348 {
349 $post = get_post();
350 if (!$post instanceof \WP_Post) {
351 return;
352 }
353
354 $items = $settings['kng_meta_items'] ?? [];
355 if (empty($items)) {
356 $items = [
357 ['kng_meta_type' => 'date'],
358 ['kng_meta_type' => 'author'],
359 ['kng_meta_type' => 'categories'],
360 ['kng_meta_type' => 'tags'],
361 ['kng_meta_type' => 'comments'],
362 ];
363 }
364
365 $output = [];
366 $separator = isset($settings['kng_separator']) ? (string) $settings['kng_separator'] : '•';
367 $terms_link = 'yes' === ($settings['kng_terms_link'] ?? 'yes');
368 $author_link = 'yes' === ($settings['kng_author_link'] ?? 'yes');
369
370 foreach ($items as $item) {
371 $type = $item['kng_meta_type'] ?? '';
372 switch ($type) {
373 case 'date':
374 $output[] = esc_html($this->get_formatted_date($settings, $post));
375 break;
376 case 'author':
377 $author = get_the_author_meta('display_name', $post->post_author);
378 if ($author) {
379 if ($author_link) {
380 $url = get_author_posts_url($post->post_author);
381 $output[] = sprintf(
382 '<a href="%1$s">%2$s</a>',
383 esc_url($url),
384 esc_html($author)
385 );
386 } else {
387 $output[] = esc_html($author);
388 }
389 }
390 break;
391 case 'categories':
392 $cats = get_the_category($post->ID);
393 if (!empty($cats)) {
394 $cat_parts = [];
395 foreach ($cats as $cat) {
396 $name = esc_html($cat->name);
397 if ($terms_link) {
398 $cat_parts[] = '<a href="' . esc_url(get_category_link($cat)) . '">' . $name . '</a>';
399 } else {
400 $cat_parts[] = $name;
401 }
402 }
403 $output[] = implode(', ', $cat_parts);
404 }
405 break;
406 case 'tags':
407 $tags = get_the_tags($post->ID);
408 if (!empty($tags)) {
409 $tag_parts = [];
410 foreach ($tags as $tag) {
411 $name = esc_html($tag->name);
412 if ($terms_link) {
413 $tag_parts[] = '<a href="' . esc_url(get_tag_link($tag)) . '">' . $name . '</a>';
414 } else {
415 $tag_parts[] = $name;
416 }
417 }
418 $output[] = implode(', ', $tag_parts);
419 }
420 break;
421 case 'comments':
422 $count = get_comments_number($post);
423 $output[] = sprintf(
424 _n('%s comment', '%s comments', $count, 'king-addons'),
425 number_format_i18n($count)
426 );
427 break;
428 case 'reading_time':
429 if ($is_pro) {
430 $output[] = esc_html($this->calculate_reading_time($post));
431 }
432 break;
433 default:
434 break;
435 }
436 }
437
438 $output = array_filter($output);
439 if (empty($output)) {
440 return;
441 }
442
443 $layout = $settings['kng_layout'] ?? 'inline';
444 $wrapper_classes = ['king-addons-tb-post-meta', 'king-addons-tb-post-meta--' . $layout];
445
446 echo '<div class="' . esc_attr(implode(' ', $wrapper_classes)) . '">';
447
448 if ('stacked' === $layout) {
449 foreach ($output as $part) {
450 echo '<div class="king-addons-tb-post-meta__item">' . wp_kses_post($part) . '</div>';
451 }
452 } else {
453 $last_index = count($output) - 1;
454 foreach ($output as $index => $part) {
455 echo '<span class="king-addons-tb-post-meta__item">' . wp_kses_post($part) . '</span>';
456 if ($index !== $last_index) {
457 echo '<span class="king-addons-tb-post-meta__separator">' . esc_html($separator) . '</span>';
458 }
459 }
460 }
461
462 echo '</div>';
463 }
464
465 /**
466 * Get formatted date.
467 *
468 * @param array<string, mixed> $settings Settings.
469 * @param \WP_Post $post Post instance.
470 *
471 * @return string
472 */
473 protected function get_formatted_date(array $settings, \WP_Post $post): string
474 {
475 $format = $settings['kng_date_format'] ?? 'default';
476 if ('custom' === $format && !empty($settings['kng_date_format_custom'])) {
477 return get_the_date(sanitize_text_field($settings['kng_date_format_custom']), $post);
478 }
479
480 if ('medium' === $format) {
481 return get_the_date('M j, Y', $post);
482 }
483
484 return get_the_date('', $post);
485 }
486
487 /**
488 * Calculate reading time.
489 *
490 * @param \WP_Post $post Post instance.
491 *
492 * @return string
493 */
494 protected function calculate_reading_time(\WP_Post $post): string
495 {
496 $content = wp_strip_all_tags((string) $post->post_content);
497 $words = str_word_count($content);
498 $minutes = max(1, (int) ceil($words / 200));
499
500 return sprintf(
501 _n('%s min read', '%s mins read', $minutes, 'king-addons'),
502 number_format_i18n($minutes)
503 );
504 }
505 }
506