Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/elementor/includes/widgets/heading.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + namespace Elementor;
3 +
4 + if ( ! defined( 'ABSPATH' ) ) {
5 + exit; // Exit if accessed directly.
6 + }
7 +
8 + use Elementor\Core\Kits\Documents\Tabs\Global_Colors;
9 + use Elementor\Core\Kits\Documents\Tabs\Global_Typography;
10 + use Elementor\Modules\ContentSanitizer\Interfaces\Sanitizable;
11 + use Elementor\Core\Utils\Hints;
12 + use Elementor\Core\Admin\Admin_Notices;
13 + use Elementor\Modules\Promotions\Controls\Promotion_Control;
14 +
15 + /**
16 + * Elementor heading widget.
17 + *
18 + * Elementor widget that displays an eye-catching headlines.
19 + *
20 + * @since 1.0.0
21 + */
22 + class Widget_Heading extends Widget_Base implements Sanitizable {
23 +
24 + /**
25 + * Get widget name.
26 + *
27 + * Retrieve heading widget name.
28 + *
29 + * @since 1.0.0
30 + * @access public
31 + *
32 + * @return string Widget name.
33 + */
34 + public function get_name() {
35 + return 'heading';
36 + }
37 +
38 + /**
39 + * Get widget title.
40 + *
41 + * Retrieve heading widget title.
42 + *
43 + * @since 1.0.0
44 + * @access public
45 + *
46 + * @return string Widget title.
47 + */
48 + public function get_title() {
49 + return esc_html__( 'Heading', 'elementor' );
50 + }
51 +
52 + /**
53 + * Get widget icon.
54 + *
55 + * Retrieve heading widget icon.
56 + *
57 + * @since 1.0.0
58 + * @access public
59 + *
60 + * @return string Widget icon.
61 + */
62 + public function get_icon() {
63 + return 'eicon-t-letter';
64 + }
65 +
66 + /**
67 + * Get widget categories.
68 + *
69 + * Retrieve the list of categories the heading widget belongs to.
70 + *
71 + * Used to determine where to display the widget in the editor.
72 + *
73 + * @since 2.0.0
74 + * @access public
75 + *
76 + * @return array Widget categories.
77 + */
78 + public function get_categories() {
79 + return [ 'basic' ];
80 + }
81 +
82 + /**
83 + * Get widget keywords.
84 + *
85 + * Retrieve the list of keywords the widget belongs to.
86 + *
87 + * @since 2.1.0
88 + * @access public
89 + *
90 + * @return array Widget keywords.
91 + */
92 + public function get_keywords() {
93 + return [ 'heading', 'title', 'text' ];
94 + }
95 +
96 + protected function is_dynamic_content(): bool {
97 + return false;
98 + }
99 +
100 + /**
101 + * Get style dependencies.
102 + *
103 + * Retrieve the list of style dependencies the widget requires.
104 + *
105 + * @since 3.24.0
106 + * @access public
107 + *
108 + * @return array Widget style dependencies.
109 + */
110 + public function get_style_depends(): array {
111 + return [ 'widget-heading' ];
112 + }
113 +
114 + public function has_widget_inner_wrapper(): bool {
115 + return ! Plugin::$instance->experiments->is_feature_active( 'e_optimized_markup' );
116 + }
117 +
118 + /**
119 + * Remove data attributes from the html.
120 + *
121 + * @param string $content Heading title.
122 + * @return string
123 + */
124 + public function sanitize( $content ): string {
125 + $allowed_tags = wp_kses_allowed_html( 'post' );
126 + $allowed_tags_for_heading = [];
127 + $non_allowed_tags = [ 'img' ];
128 +
129 + foreach ( $allowed_tags as $tag => $attributes ) {
130 + if ( in_array( $tag, $non_allowed_tags, true ) ) {
131 + continue;
132 + }
133 +
134 + $filtered_attributes = array_filter( $attributes, function( $attribute ) {
135 + return ! substr( $attribute, 0, 5 ) === 'data-';
136 + }, ARRAY_FILTER_USE_KEY );
137 +
138 + $allowed_tags_for_heading[ $tag ] = $filtered_attributes;
139 + }
140 +
141 + return wp_kses( $content, $allowed_tags_for_heading );
142 + }
143 +
144 + /**
145 + * Get widget upsale data.
146 + *
147 + * Retrieve the widget promotion data.
148 + *
149 + * @since 3.18.0
150 + * @access protected
151 + *
152 + * @return array Widget promotion data.
153 + */
154 + protected function get_upsale_data() {
155 + return [
156 + 'condition' => ! Utils::has_pro(),
157 + 'image' => esc_url( ELEMENTOR_ASSETS_URL . 'images/go-pro.svg' ),
158 + 'image_alt' => esc_attr__( 'Upgrade', 'elementor' ),
159 + 'description' => esc_html__( 'Create captivating headings that rotate with the Animated Headline Widget.', 'elementor' ),
160 + 'upgrade_url' => esc_url( 'https://go.elementor.com/go-pro-heading-widget/' ),
161 + 'upgrade_text' => esc_html__( 'Upgrade Now', 'elementor' ),
162 + ];
163 + }
164 +
165 + /**
166 + * Register heading widget controls.
167 + *
168 + * Adds different input fields to allow the user to change and customize the widget settings.
169 + *
170 + * @since 3.1.0
171 + * @access protected
172 + */
173 + protected function register_controls() {
174 + $this->start_controls_section(
175 + 'section_title',
176 + [
177 + 'label' => esc_html__( 'Heading', 'elementor' ),
178 + ]
179 + );
180 +
181 + $this->add_control(
182 + 'title',
183 + [
184 + 'label' => esc_html__( 'Title', 'elementor' ),
185 + 'type' => Controls_Manager::TEXTAREA,
186 + 'ai' => [
187 + 'type' => 'text',
188 + ],
189 + 'dynamic' => [
190 + 'active' => true,
191 + ],
192 + 'placeholder' => esc_html__( 'Enter your title', 'elementor' ),
193 + 'default' => esc_html__( 'Add Your Heading Text Here', 'elementor' ),
194 + ]
195 + );
196 +
197 + $this->add_control(
198 + 'link',
199 + [
200 + 'label' => esc_html__( 'Link', 'elementor' ),
201 + 'type' => Controls_Manager::URL,
202 + 'dynamic' => [
203 + 'active' => true,
204 + ],
205 + 'default' => [
206 + 'url' => '',
207 + ],
208 + ]
209 + );
210 +
211 + $this->add_control(
212 + 'size',
213 + [
214 + 'label' => esc_html__( 'Size', 'elementor' ),
215 + 'type' => Controls_Manager::SELECT,
216 + 'options' => [
217 + 'default' => esc_html__( 'Default', 'elementor' ),
218 + 'small' => esc_html__( 'Small', 'elementor' ),
219 + 'medium' => esc_html__( 'Medium', 'elementor' ),
220 + 'large' => esc_html__( 'Large', 'elementor' ),
221 + 'xl' => esc_html__( 'XL', 'elementor' ),
222 + 'xxl' => esc_html__( 'XXL', 'elementor' ),
223 + ],
224 + 'default' => 'default',
225 + 'condition' => [
226 + 'size!' => 'default', // a workaround to hide the control, unless it's in use (not default).
227 + ],
228 + ]
229 + );
230 +
231 + $this->add_control(
232 + 'header_size',
233 + [
234 + 'label' => esc_html__( 'HTML Tag', 'elementor' ),
235 + 'type' => Controls_Manager::SELECT,
236 + 'options' => [
237 + 'h1' => 'H1',
238 + 'h2' => 'H2',
239 + 'h3' => 'H3',
240 + 'h4' => 'H4',
241 + 'h5' => 'H5',
242 + 'h6' => 'H6',
243 + 'div' => 'div',
244 + 'span' => 'span',
245 + 'p' => 'p',
246 + ],
247 + 'default' => 'h2',
248 + ]
249 + );
250 +
251 + $this->maybe_add_ally_heading_hint();
252 +
253 + $this->end_controls_section();
254 +
255 + $this->start_controls_section(
256 + 'section_title_style',
257 + [
258 + 'label' => esc_html__( 'Heading', 'elementor' ),
259 + 'tab' => Controls_Manager::TAB_STYLE,
260 + ]
261 + );
262 +
263 + $this->add_responsive_control(
264 + 'align',
265 + [
266 + 'label' => esc_html__( 'Alignment', 'elementor' ),
267 + 'type' => Controls_Manager::CHOOSE,
268 + 'options' => [
269 + 'start' => [
270 + 'title' => esc_html__( 'Start', 'elementor' ),
271 + 'icon' => 'eicon-text-align-left',
272 + ],
273 + 'center' => [
274 + 'title' => esc_html__( 'Center', 'elementor' ),
275 + 'icon' => 'eicon-text-align-center',
276 + ],
277 + 'end' => [
278 + 'title' => esc_html__( 'End', 'elementor' ),
279 + 'icon' => 'eicon-text-align-right',
280 + ],
281 + 'justify' => [
282 + 'title' => esc_html__( 'Justified', 'elementor' ),
283 + 'icon' => 'eicon-text-align-justify',
284 + ],
285 + ],
286 + 'classes' => 'elementor-control-start-end',
287 + 'selectors_dictionary' => [
288 + 'left' => is_rtl() ? 'end' : 'start',
289 + 'right' => is_rtl() ? 'start' : 'end',
290 + ],
291 + 'default' => '',
292 + 'selectors' => [
293 + '{{WRAPPER}}' => 'text-align: {{VALUE}};',
294 + ],
295 + 'separator' => 'after',
296 + ]
297 + );
298 +
299 + $this->add_group_control(
300 + Group_Control_Typography::get_type(),
301 + [
302 + 'name' => 'typography',
303 + 'global' => [
304 + 'default' => Global_Typography::TYPOGRAPHY_PRIMARY,
305 + ],
306 + 'selector' => '{{WRAPPER}} .elementor-heading-title',
307 + ]
308 + );
309 +
310 + $this->add_group_control(
311 + Group_Control_Text_Stroke::get_type(),
312 + [
313 + 'name' => 'text_stroke',
314 + 'selector' => '{{WRAPPER}} .elementor-heading-title',
315 + ]
316 + );
317 +
318 + $this->add_group_control(
319 + Group_Control_Text_Shadow::get_type(),
320 + [
321 + 'name' => 'text_shadow',
322 + 'selector' => '{{WRAPPER}} .elementor-heading-title',
323 + ]
324 + );
325 +
326 + $this->add_control(
327 + 'blend_mode',
328 + [
329 + 'label' => esc_html__( 'Blend Mode', 'elementor' ),
330 + 'type' => Controls_Manager::SELECT,
331 + 'options' => [
332 + '' => esc_html__( 'Normal', 'elementor' ),
333 + 'multiply' => esc_html__( 'Multiply', 'elementor' ),
334 + 'screen' => esc_html__( 'Screen', 'elementor' ),
335 + 'overlay' => esc_html__( 'Overlay', 'elementor' ),
336 + 'darken' => esc_html__( 'Darken', 'elementor' ),
337 + 'lighten' => esc_html__( 'Lighten', 'elementor' ),
338 + 'color-dodge' => esc_html__( 'Color Dodge', 'elementor' ),
339 + 'saturation' => esc_html__( 'Saturation', 'elementor' ),
340 + 'color' => esc_html__( 'Color', 'elementor' ),
341 + 'difference' => esc_html__( 'Difference', 'elementor' ),
342 + 'exclusion' => esc_html__( 'Exclusion', 'elementor' ),
343 + 'hue' => esc_html__( 'Hue', 'elementor' ),
344 + 'luminosity' => esc_html__( 'Luminosity', 'elementor' ),
345 + ],
346 + 'selectors' => [
347 + '{{WRAPPER}} .elementor-heading-title' => 'mix-blend-mode: {{VALUE}}',
348 + ],
349 + ]
350 + );
351 +
352 + $this->add_control(
353 + 'separator',
354 + [
355 + 'type' => Controls_Manager::DIVIDER,
356 + ]
357 + );
358 +
359 + $this->start_controls_tabs( 'title_colors' );
360 +
361 + $this->start_controls_tab(
362 + 'title_colors_normal',
363 + [
364 + 'label' => esc_html__( 'Normal', 'elementor' ),
365 + ]
366 + );
367 +
368 + $this->add_control(
369 + 'title_color',
370 + [
371 + 'label' => esc_html__( 'Text Color', 'elementor' ),
372 + 'type' => Controls_Manager::COLOR,
373 + 'global' => [
374 + 'default' => Global_Colors::COLOR_PRIMARY,
375 + ],
376 + 'selectors' => [
377 + '{{WRAPPER}} .elementor-heading-title' => 'color: {{VALUE}};',
378 + ],
379 + ]
380 + );
381 +
382 + $this->end_controls_tab();
383 +
384 + $this->start_controls_tab(
385 + 'title_colors_hover',
386 + [
387 + 'label' => esc_html__( 'Hover', 'elementor' ),
388 + ]
389 + );
390 +
391 + $this->add_control(
392 + 'title_hover_color',
393 + [
394 + 'label' => esc_html__( 'Link Color', 'elementor' ),
395 + 'type' => Controls_Manager::COLOR,
396 + 'selectors' => [
397 + '{{WRAPPER}} .elementor-heading-title a:hover, {{WRAPPER}} .elementor-heading-title a:focus' => 'color: {{VALUE}};',
398 + ],
399 + ]
400 + );
401 +
402 + $this->add_control(
403 + 'title_hover_color_transition_duration',
404 + [
405 + 'label' => esc_html__( 'Transition Duration', 'elementor' ),
406 + 'type' => Controls_Manager::SLIDER,
407 + 'size_units' => [ 's', 'ms', 'custom' ],
408 + 'default' => [
409 + 'unit' => 's',
410 + ],
411 + 'selectors' => [
412 + '{{WRAPPER}} .elementor-heading-title a' => 'transition-duration: {{SIZE}}{{UNIT}};',
413 + ],
414 + ]
415 + );
416 +
417 + $this->end_controls_tab();
418 +
419 + $this->end_controls_tabs();
420 +
421 + $this->end_controls_section();
422 + }
423 +
424 + /**
425 + * Render heading widget output on the frontend.
426 + *
427 + * Written in PHP and used to generate the final HTML.
428 + *
429 + * @since 1.0.0
430 + * @access protected
431 + */
432 + protected function render() {
433 + $settings = $this->get_settings_for_display();
434 +
435 + if ( '' === $settings['title'] ) {
436 + return;
437 + }
438 +
439 + $this->add_render_attribute( 'title', 'class', 'elementor-heading-title' );
440 +
441 + if ( ! empty( $settings['size'] ) ) {
442 + $this->add_render_attribute( 'title', 'class', 'elementor-size-' . $settings['size'] );
443 + } else {
444 + $this->add_render_attribute( 'title', 'class', 'elementor-size-default' );
445 + }
446 +
447 + $this->add_inline_editing_attributes( 'title' );
448 +
449 + $title = wp_kses_post( $settings['title'] );
450 +
451 + if ( ! empty( $settings['link']['url'] ) ) {
452 + $this->add_link_attributes( 'url', $settings['link'] );
453 +
454 + $title = sprintf( '<a %1$s>%2$s</a>', $this->get_render_attribute_string( 'url' ), $title );
455 + }
456 +
457 + $title_html = sprintf( '<%1$s %2$s>%3$s</%1$s>', Utils::validate_html_tag( $settings['header_size'] ), $this->get_render_attribute_string( 'title' ), $title );
458 +
459 + // PHPCS - the variable $title_html holds safe data.
460 + echo $title_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
461 + }
462 +
463 + public function maybe_add_ally_heading_hint() {
464 + $notice_id = 'ally_heading_notice';
465 + $plugin_slug = 'pojo-accessibility';
466 + if ( ! Hints::should_display_hint( $notice_id ) ) {
467 + return;
468 + }
469 + $notice_content = esc_html__( 'Make sure your page is structured with accessibility in mind. Ally helps detect and fix common issues across your site.', 'elementor' );
470 +
471 + $campaign_data = [
472 + 'name' => 'elementor_ea11y_campaign',
473 + 'campaign' => 'acc-scanner-plg-heading',
474 + 'source' => 'editor-heading-widget',
475 + 'medium' => 'editor',
476 + ];
477 +
478 + $button_text = __( 'Install Plugin', 'elementor' );
479 + $action_url = Admin_Notices::add_plg_campaign_data( Hints::get_plugin_action_url( $plugin_slug ), $campaign_data );
480 +
481 + if ( Hints::is_plugin_installed( $plugin_slug ) && ! Hints::is_plugin_active( $plugin_slug ) ) {
482 + $button_text = __( 'Activate Plugin', 'elementor' );
483 + } elseif ( Hints::is_plugin_active( $plugin_slug ) && empty( get_option( 'ea11y_access_token' ) ) ) {
484 + $button_text = __( 'Connect to Ally', 'elementor' );
485 + $action_url = admin_url( 'admin.php?page=accessibility-settings' );
486 + }
487 +
488 + $this->add_control(
489 + $notice_id,
490 + [
491 + 'type' => Controls_Manager::RAW_HTML,
492 + 'raw' => Hints::get_notice_template( [
493 + 'display' => ! Hints::is_dismissed( $notice_id ),
494 + 'heading' => esc_html__( 'Accessible structure matters', 'elementor' ),
495 + 'type' => 'info',
496 + 'content' => $notice_content,
497 + 'icon' => true,
498 + 'dismissible' => $notice_id,
499 + 'button_text' => $button_text,
500 + 'button_event' => $notice_id,
501 + 'button_data' => [
502 + 'action_url' => $action_url,
503 + ],
504 + ], true ),
505 + ]
506 + );
507 + }
508 +
509 + /**
510 + * Render heading widget output in the editor.
511 + *
512 + * Written as a Backbone JavaScript template and used to generate the live preview.
513 + *
514 + * @since 2.9.0
515 + * @access protected
516 + */
517 + protected function content_template() {
518 + ?>
519 + <#
520 + let title = elementor.helpers.sanitize( settings.title, { ALLOW_DATA_ATTR: false } );
521 +
522 + if ( '' !== settings.link?.url ) {
523 + title = '<a href="' + elementor.helpers.sanitizeUrl( settings.link?.url ) + '">' + title + '</a>';
524 + }
525 +
526 + view.addRenderAttribute( 'title', 'class', [ 'elementor-heading-title' ] );
527 +
528 + if ( '' !== settings.size ) {
529 + view.addRenderAttribute( 'title', 'class', [ 'elementor-size-' + settings.size ] );
530 + } else {
531 + view.addRenderAttribute( 'title', 'class', [ 'elementor-size-default' ] );
532 + }
533 +
534 + view.addInlineEditingAttributes( 'title' );
535 +
536 + var headerSizeTag = elementor.helpers.validateHTMLTag( settings.header_size ),
537 + title_html = '<' + headerSizeTag + ' ' + view.getRenderAttributeString( 'title' ) + '>' + title + '</' + headerSizeTag + '>';
538 +
539 + print( title_html );
540 + #>
541 + <?php
542 + }
543 + }
544 +