Changeset 3425008
- Timestamp:
- 12/22/2025 03:16:34 AM (3 months ago)
- Location:
- breadcrumb-navxt/trunk
- Files:
-
- 15 edited
-
breadcrumb-navxt.php (modified) (17 diffs)
-
class.bcn_admin.php (modified) (49 diffs)
-
class.bcn_breadcrumb.php (modified) (7 diffs)
-
class.bcn_breadcrumb_trail.php (modified) (14 diffs)
-
class.bcn_network_admin.php (modified) (14 diffs)
-
class.bcn_rest_controller.php (modified) (1 diff)
-
class.bcn_widget.php (modified) (5 diffs)
-
includes/adminKit/class-mtekk_adminkit.php (modified) (63 diffs)
-
includes/adminKit/class-mtekk_adminkit_form.php (modified) (11 diffs)
-
includes/adminKit/class-mtekk_adminkit_message.php (modified) (4 diffs)
-
includes/adminKit/setting/class-mtekk_adminkit_setting_string.php (modified) (1 diff)
-
includes/blocks/build/breadcrumb-trail/block.json (modified) (1 diff)
-
includes/blocks/build/breadcrumb-trail/render.php (modified) (7 diffs)
-
options_upgrade.php (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
breadcrumb-navxt/trunk/breadcrumb-navxt.php
r3411622 r3425008 4 4 Plugin URI: http://mtekk.us/code/breadcrumb-navxt/ 5 5 Description: Adds a breadcrumb navigation showing the visitor's path to their current location. For details on how to use this plugin visit <a href="http://mtekk.us/code/breadcrumb-navxt/">Breadcrumb NavXT</a>. 6 Version: 7.5. 06 Version: 7.5.1 7 7 Author: John Havlik 8 8 Author URI: http://mtekk.us/ … … 34 34 function bcn_phpold() 35 35 { 36 printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.6.0'); 36 /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */ 37 printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0'); 37 38 } 38 39 //If we are in the admin, let's print a warning then return … … 64 65 class breadcrumb_navxt 65 66 { 66 const version = '7.5. 0';67 const version = '7.5.1'; 67 68 protected $name = 'Breadcrumb NavXT'; 68 69 protected $identifier = 'breadcrumb-navxt'; … … 355 356 $settings['Hpaged_template'] = new setting\setting_html( 356 357 'paged_template', 358 /* translators: %htitle%: The page title which may contain HTML */ 357 359 sprintf('<span class="%%type%%">%1$s</span>', esc_attr__('Page %htitle%', 'breadcrumb-navxt')), 358 360 _x('Paged Template', 'Paged as in when on an archive or post that is split into multiple pages', 'breadcrumb-navxt')); … … 372 374 'post_' . $post_type->name . '_template', 373 375 bcn_breadcrumb::get_default_template(), 376 /* translators: %s: The singular name of the post type */ 374 377 sprintf(__('%s Template', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 375 378 $settings['Hpost_' . $post_type->name . '_template_no_anchor'] = new setting\setting_html( 376 379 'post_' . $post_type->name . '_template_no_anchor', 377 380 bcn_breadcrumb::default_template_no_anchor, 381 /* translators: %s: The singular name of the post type */ 378 382 sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 379 383 //Root default depends on post type … … 393 397 'post_' . $post_type->name . '_root', 394 398 $default_root, 399 /* translators: %s: The singular name of the post type */ 395 400 sprintf(__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 396 401 //Archive display default depends on post type … … 406 411 'post_' . $post_type->name . '_archive_display', 407 412 $default_archive_display, 413 /* translators: %s: The singular name of the post type */ 408 414 sprintf(__('%s Archive Display', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 409 415 $settings['bpost_' . $post_type->name . '_taxonomy_referer'] = new setting\setting_bool( 410 416 'post_' . $post_type->name . '_taxonomy_referer', 411 417 false, 418 /* translators: %s: The singular name of the post type */ 412 419 sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 413 420 //Hierarchy use parent first depends on post type … … 427 434 'post_' . $post_type->name . '_hierarchy_parent_first', 428 435 $default_parent_first, 436 /* translators: %s: The singular name of the post type */ 429 437 sprintf(__('%s Hierarchy Use Parent First', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 430 438 //Hierarchy depends on post type … … 470 478 'post_' . $post_type->name . '_hierarchy_display', 471 479 $default_hierarchy_display, 480 /* translators: %s: The singular name of the post type */ 472 481 sprintf(__('%s Hierarchy Display', 'breadcrumb-navxt'), $post_type->labels->singular_name)); 473 482 $settings['Epost_' . $post_type->name . '_hierarchy_type'] = new setting\setting_enum( 474 483 'post_' . $post_type->name . '_hierarchy_type', 475 484 $hierarchy_type_default, 485 /* translators: %s: The singular name of the post type */ 476 486 sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name), 477 487 false, … … 484 494 $settings['Htax_' . $taxonomy->name. '_template'] = new setting\setting_html( 485 495 'tax_' . $taxonomy->name. '_template', 486 __(sprintf('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="Go to the %%title%% %s archives." href="%%link%%" class="%%type%%" bcn-aria-current><span property="name">%%htitle%%</span></a><meta property="position" content="%%position%%"></span>', $taxonomy->labels->singular_name), 'breadcrumb-navxt'), 496 /* translators: %s: The singular name of the taxonomy */ 497 sprintf('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="%s" href="%%link%%" class="%%type%%" bcn-aria-current><span property="name">%%htitle%%</span></a><meta property="position" content="%%position%%"></span>', sprintf(esc_attr__('Go to the %%title%% %s archives.', 'breadcrumb-navxt'), $taxonomy->labels->singular_name)), 498 /* translators: %s: The singular name of the taxonomy */ 487 499 sprintf(__('%s Template', 'breadcrumb-navxt'), $taxonomy->labels->singular_name)); 488 500 $settings['Htax_' . $taxonomy->name. '_template_no_anchor'] = new setting\setting_html( 489 501 'tax_' . $taxonomy->name. '_template_no_anchor', 490 502 bcn_breadcrumb::default_template_no_anchor, 503 /* translators: %s: The singular name of the taxonomy */ 491 504 sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $taxonomy->labels->singular_name)); 492 505 } … … 503 516 'search_template', 504 517 sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>', 518 /* translators: %s: The searched phrase */ 505 519 sprintf(esc_attr__('Search results for '%1$s'', 'breadcrumb-navxt'), 506 520 sprintf('<a property="item" typeof="WebPage" title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of search results for %title%.', 'breadcrumb-navxt')))), … … 509 523 'search_template_no_anchor', 510 524 sprintf('<span class="%%type%%">%1$s</span>', 525 /* translators: %s: The searched phrase */ 511 526 sprintf(esc_attr__('Search results for '%1$s'', 'breadcrumb-navxt'), '%htitle%')), 512 527 __('Search Template (Unlinked)', 'breadcrumb-navxt')); … … 522 537 'author_template', 523 538 sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>', 539 /* translators: %s: The post author name the current archive is for */ 524 540 sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), 525 541 sprintf('<a title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of posts by %title%.', 'breadcrumb-navxt')))), … … 528 544 'author_template_no_anchor', 529 545 sprintf('<span class="%%type%%">%1$s</span>', 546 /* translators: %s: The post author name the current archive is for */ 530 547 sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')), 531 548 __('Author Template (Unlinked)', 'breadcrumb-navxt')); … … 594 611 //Generate the breadcrumb trail 595 612 $this->breadcrumb_trail->fill_REST($post); 596 $trail_string = $this->breadcrumb_trail->display($linked, $reverse, $template);613 $trail_string_safe = $this->breadcrumb_trail->display($linked, $reverse, $template); 597 614 if($return) 598 615 { 599 return $trail_string ;616 return $trail_string_safe; 600 617 } 601 618 else 602 619 { 603 //Helps track issues, please don't remove it 604 $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n"; 605 echo $credits . $trail_string; 620 echo $trail_string_safe; 606 621 } 607 622 } … … 673 688 //Generate the breadcrumb trail 674 689 $this->breadcrumb_trail->fill($force); 675 $trail_string = $this->breadcrumb_trail->display($linked, $reverse, $template, $outer_template);690 $trail_string_safe = $this->breadcrumb_trail->display($linked, $reverse, $template, $outer_template); 676 691 if($return) 677 692 { 678 return $trail_string ;693 return $trail_string_safe; 679 694 } 680 695 else 681 696 { 682 //Helps track issues, please don't remove it 683 $credits = "<!-- Breadcrumb NavXT " . $this::version . " -->\n"; 684 echo $credits . $trail_string; 697 echo $trail_string_safe; 685 698 } 686 699 } … … 722 735 //Generate the breadcrumb trail 723 736 $this->breadcrumb_trail->fill($force); 724 $trail_string =json_encode($this->breadcrumb_trail->display_json_ld($reverse), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);737 $trail_string_safe = wp_json_encode($this->breadcrumb_trail->display_json_ld($reverse), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); 725 738 if($return) 726 739 { 727 return $trail_string ;740 return $trail_string_safe; 728 741 } 729 742 else 730 743 { 731 echo $trail_string ;744 echo $trail_string_safe; 732 745 } 733 746 } -
breadcrumb-navxt/trunk/class.bcn_admin.php
r3411622 r3425008 24 24 function bcn_phpold() 25 25 { 26 printf('<div class="notice notice-error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.6.0'); 26 /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */ 27 printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0'); 27 28 } 28 29 //If we are in the admin, let's print a warning then return … … 60 61 * @param array $settings The array of settings objects 61 62 */ 62 function __construct(array &$opts, $basename, array &$settings)63 public function __construct(array &$opts, $basename, array &$settings) 63 64 { 64 65 $this->plugin_basename = $basename; … … 69 70 parent::__construct(); 70 71 } 71 function is_network_admin()72 public function is_network_admin() 72 73 { 73 74 return false; … … 78 79 * @param array $opts The opts array 79 80 */ 80 function setting_merge($opts)81 public function setting_merge($opts) 81 82 { 82 83 $unknown = array(); … … 106 107 { 107 108 $this->messages[] = new message( 108 sprintf(__('Found %u unknown legacy settings: %s','breadcrumb-navxt'), count($unknown), implode(', ', $unknown)), 109 /* translators: %u: Number of unknown legacy settings found, %s: comma separated list of the setting names */ 110 sprintf(__('Found %1$u unknown legacy settings: %2$s','breadcrumb-navxt'), count($unknown), implode(', ', $unknown)), 109 111 'warning', 110 112 true, … … 120 122 * @return void 121 123 */ 122 function init()124 public function init() 123 125 { 124 126 //We're going to make sure we run the parent's version of this function as well … … 132 134 * @param string $version the version of the passed in options 133 135 */ 134 function opts_upgrade($opts, $version)136 public function opts_upgrade($opts, $version) 135 137 { 136 138 //If our version is not the same as in the db, time to update … … 148 150 * @param WP_Screen $screen The screen to add the help tab items to 149 151 */ 150 function help_contents(\WP_Screen &$screen)152 public function help_contents(\WP_Screen &$screen) 151 153 { 152 154 $general_tab = '<p>' . esc_html__('Tips for the settings are located below select options.', 'breadcrumb-navxt') . … … 216 218 * enqueue's the tab style sheet on the settings page 217 219 */ 218 function admin_styles()220 public function admin_styles() 219 221 { 220 222 wp_enqueue_style('mtekk_adminkit_tabs'); … … 223 225 * enqueue's the tab js and translation js on the settings page 224 226 */ 225 function admin_scripts()227 public function admin_scripts() 226 228 { 227 229 //Enqueue ui-tabs … … 242 244 * A message function that checks for the BCN_SETTINGS_* define statement 243 245 */ 244 function multisite_settings_warn()246 public function multisite_settings_warn() 245 247 { 246 248 if(is_multisite()) … … 272 274 * A message function that checks for deprecated settings that are set and warns the user 273 275 */ 274 function deprecated_settings_warn()276 public function deprecated_settings_warn() 275 277 { 276 278 //We're deprecating the limit title length setting, let the user know the new method of accomplishing this … … 279 281 $this->messages[] = new message( 280 282 sprintf( 283 /* translators: %1$s: HTML opening tag for link to article, %2$s: HTML closing tag for link to article */ 281 284 esc_html__('Error: The deprecated setting "Title Length" (see Miscellaneous > Deprecated) has no effect in this version Breadcrumb NavXT. Please %1$suse CSS instead%2$s.', 'breadcrumb-navxt'), 282 '<a title="' . __('Go to the guide on trimming breadcrumb title lengths with CSS', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/guides/trimming-breadcrumb-title-lengths-with-css/">', '</a>'),285 '<a title="' . esc_attr__('Go to the guide on trimming breadcrumb title lengths with CSS', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/guides/trimming-breadcrumb-title-lengths-with-css/">', '</a>'), 283 286 'error'); 284 287 } … … 306 309 $this->messages[] = new message( 307 310 sprintf( 311 /* translators: %1$s: Name of the deprecated template tag found, %2$s: Recommended replacement tag for the deprecated tag, %3$s: The setting name where the deprecated tag was found */ 308 312 esc_html__('Error: The deprecated template tag %1$s found in setting %3$s. Please use %2$s instead.', 'breadcrumb-navxt'), 309 313 implode(' and ', $deprecated_tags), … … 318 322 * A message function that checks for post types added after the settings defaults were established 319 323 */ 320 function unknown_custom_types_warn()324 public function unknown_custom_types_warn() 321 325 { 322 326 foreach($GLOBALS['wp_post_types'] as $post_type) … … 326 330 $this->messages[] = new message( 327 331 sprintf( 332 /* translators: %1$s: Export of the post_type object of the unexpected CPT */ 328 333 esc_html__('Error: WP_Post_Types global contains non WP_Post_Type object. Debug information: %1$s', 'breadcrumb-navxt'), 329 334 var_export($post_type, true)), … … 338 343 $this->messages[] = new message( 339 344 sprintf( 345 /* translators: %1$s: Post type singular name, %2$s: Post type name */ 340 346 esc_html__('Warning: The post type %1$s (%2$s) was registered after the Breadcrumb NavXT default settings. It will not show up in the settings.', 'breadcrumb-navxt'), 341 347 $post_type->labels->singular_name, … … 353 359 $this->messages[] = new message( 354 360 sprintf( 361 /* translators: %1$s: Export of the taxonomy object of the unexpected custom taxonomy */ 355 362 esc_html__('Error: WP_Taxonomies global contains non WP_Taxonomy object. Debug information: %1$s', 'breadcrumb-navxt'), 356 363 var_export($taxonomy, true)), … … 365 372 $this->messages[] = new message( 366 373 sprintf( 374 /* translators: %1$s: Taxonomy label, %2$s: Taxonomy name */ 367 375 esc_html__('Warning: The taxonomy %1$s (%2$s) was registered after the Breadcrumb NavXT default settings. It will not show up in the settings.', 'breadcrumb-navxt'), 368 376 $taxonomy->label, … … 379 387 * @return boool Whether or not the blog options should be disabled 380 388 */ 381 function maybe_disable_blog_options()389 public function maybe_disable_blog_options() 382 390 { 383 391 return (get_option('show_on_front') !== 'page' || get_option('page_for_posts') < 1); … … 388 396 * @return bool Whether or not the mainsite options should be disabled 389 397 */ 390 function maybe_disable_mainsite_options()398 public function maybe_disable_mainsite_options() 391 399 { 392 400 return !is_multisite(); … … 395 403 * The administrative page for Breadcrumb NavXT 396 404 */ 397 function admin_page()405 public function admin_page() 398 406 { 399 407 global $wp_taxonomies, $wp_post_types; … … 432 440 } 433 441 ?> 434 <div class="wrap"><h1><?php echo $this->full_name; ?></h1>442 <div class="wrap"><h1><?php echo esc_html($this->full_name); ?></h1> 435 443 <?php 436 444 //We exit after the version check if there is an action the user needs to take before saving settings … … 440 448 } 441 449 ?> 442 <form action="<?php echo $this->admin_url(); ?>" method="post" id="bcn_admin-options">450 <form action="<?php echo esc_attr($this->admin_url()); ?>" method="post" id="bcn_admin-options"> 443 451 <?php settings_fields('bcn_options');?> 444 452 <div id="hasadmintabs"> 445 453 <fieldset id="general" class="bcn_options"> 446 <legend class="screen-reader-text" data-title="<?php _e( 'A collection of settings most likely to be modified are located under this tab.', 'breadcrumb-navxt' );?>"><?php_e( 'General', 'breadcrumb-navxt' ); ?></legend>447 <h2><?php _e('General', 'breadcrumb-navxt'); ?></h2>454 <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'A collection of settings most likely to be modified are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'General', 'breadcrumb-navxt' ); ?></legend> 455 <h2><?php esc_html_e('General', 'breadcrumb-navxt'); ?></h2> 448 456 <table class="form-table"> 449 457 <?php … … 452 460 ?> 453 461 </table> 454 <h2><?php _e('Current Item', 'breadcrumb-navxt'); ?></h2>462 <h2><?php esc_html_e('Current Item', 'breadcrumb-navxt'); ?></h2> 455 463 <table class="form-table adminkit-enset-top"> 456 464 <?php … … 476 484 ?> 477 485 </table> 478 <h2><?php _e('Home Breadcrumb', 'breadcrumb-navxt'); ?></h2>486 <h2><?php esc_html_e('Home Breadcrumb', 'breadcrumb-navxt'); ?></h2> 479 487 <table class="form-table adminkit-enset-top"> 480 488 <?php … … 500 508 ?> 501 509 </table> 502 <h2><?php _e('Blog Breadcrumb', 'breadcrumb-navxt'); ?></h2>510 <h2><?php esc_html_e('Blog Breadcrumb', 'breadcrumb-navxt'); ?></h2> 503 511 <table class="form-table adminkit-enset-top"> 504 512 <?php … … 512 520 ?> 513 521 </table> 514 <h2><?php _e('Mainsite Breadcrumb', 'breadcrumb-navxt'); ?></h2>522 <h2><?php esc_html_e('Mainsite Breadcrumb', 'breadcrumb-navxt'); ?></h2> 515 523 <table class="form-table adminkit-enset-top"> 516 524 <?php … … 539 547 </fieldset> 540 548 <fieldset id="post" class="bcn_options"> 541 <legend class="screen-reader-text" data-title="<?php _e( 'The settings for all post types (Posts, Pages, and Custom Post Types) are located under this tab.', 'breadcrumb-navxt' );?>"><?php_e( 'Post Types', 'breadcrumb-navxt' ); ?></legend>549 <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'The settings for all post types (Posts, Pages, and Custom Post Types) are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'Post Types', 'breadcrumb-navxt' ); ?></legend> 542 550 <?php 543 551 //Loop through all of the post types in the array … … 551 559 $singular_name_lc = mb_strtolower($post_type->labels->singular_name, 'UTF-8'); 552 560 ?> 553 <h2><?php echo $post_type->labels->singular_name; ?></h2>561 <h2><?php echo esc_html($post_type->labels->singular_name); ?></h2> 554 562 <table class="form-table adminkit-enset-top"> 555 563 <?php … … 558 566 '6', 559 567 false, 568 /* translators: %s: Singular name for the CPT */ 560 569 sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt'), $singular_name_lc) . $overridden['Hpost_' . $post_type->name . '_template'], 561 570 $overridden_style['Hpost_' . $post_type->name . '_template']); … … 564 573 '4', 565 574 false, 575 /* translators: %s: Singular name for the CPT */ 566 576 sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'), $singular_name_lc) . $overridden['Hpost_' . $post_type->name . '_template_no_anchor'], 567 577 $overridden_style['Hpost_' . $post_type->name . '_template_no_anchor']); … … 571 581 ?> 572 582 <tr valign="top"> 573 <th scope="row"> 574 <label for="<?php echo $optid;?>"><?php printf(esc_html__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name);?></label>583 <th scope="row"><?php /* translators: %s: Singular name for the CPT */ ?> 584 <label for="<?php echo esc_attr($optid);?>"><?php printf(esc_html__('%s Root Page', 'breadcrumb-navxt'), esc_html($post_type->labels->singular_name));?></label> 575 585 </th> 576 586 <td> … … 580 590 'id' => $optid, 581 591 'echo' => 1, 582 'show_option_none' => __( '— Select —'),592 'show_option_none' => esc_attr__('— Select —', 'breadcrumb-navxt'), 583 593 'option_none_value' => '0', 584 594 'selected' => $this->settings['apost_' . $post_type->name . '_root']->get_value(), … … 588 598 if(isset($overridden['apost_' . $post_type->name . '_root']) && $overridden['apost_' . $post_type->name . '_root'] !== '') 589 599 { 590 printf('<p class="description">%s</p>', $overridden['apost_' . $post_type->name . '_root']);600 printf('<p class="description">%s</p>', esc_html($overridden['apost_' . $post_type->name . '_root'])); 591 601 } 592 602 ?> … … 594 604 </tr> 595 605 <?php 596 $this->form->input_check(606 $this->form->input_check( 597 607 $this->settings['bpost_' . $post_type->name . '_archive_display'], 608 /* translators: %s: Post type singlar name */ 598 609 sprintf(__('Show the breadcrumb for the %s post type archives in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc), 599 610 !$post_type->has_archive, … … 611 622 $this->form->input_check( 612 623 $this->settings['bpost_' . $post_type->name . '_hierarchy_display'], 624 /* translators: %s: Singular name for the CPT */ 613 625 sprintf(__('Show the hierarchy (specified below) leading to a %s in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc), 614 626 false, … … 617 629 $this->form->input_check( 618 630 $this->settings['bpost_' . $post_type->name . '_hierarchy_parent_first'], 631 /* translators: %s: Singular name for the CPT */ 619 632 sprintf(__('Use the parent of the %s as the primary hierarchy, falling back to the hierarchy selected below when the parent hierarchy is exhausted.', 'breadcrumb-navxt'), $singular_name_lc), 620 633 false, … … 630 643 <tr valign="top"> 631 644 <th scope="row"> 632 <?php printf(__('%s Hierarchy', 'breadcrumb-navxt'), $post_type->labels->singular_name); ?> 645 <?php /* translators: %s: Singular name for the CPT */ 646 printf(esc_html__('%s Hierarchy', 'breadcrumb-navxt'), esc_html($post_type->labels->singular_name)); ?> 633 647 </th> 634 648 <td> … … 662 676 esc_html_e('The hierarchy which the breadcrumb trail will show. Note that the "Post Parent" option may require an additional plugin to behave as expected since this is a non-hierarchical post type.', 'breadcrumb-navxt'); 663 677 } 664 echo $overridden['Epost_' . $post_type->name . '_hierarchy_type'];678 echo esc_html($overridden['Epost_' . $post_type->name . '_hierarchy_type']); 665 679 ?> 666 680 </p> … … 677 691 </fieldset> 678 692 <fieldset id="tax" class="bcn_options alttab"> 679 <legend class="screen-reader-text" data-title="<?php _e( 'The settings for all taxonomies (including Categories, Tags, and custom taxonomies) are located under this tab.', 'breadcrumb-navxt' );?>"><?php_e( 'Taxonomies', 'breadcrumb-navxt' ); ?></legend>693 <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'The settings for all taxonomies (including Categories, Tags, and custom taxonomies) are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'Taxonomies', 'breadcrumb-navxt' ); ?></legend> 680 694 <?php 681 695 //Loop through all of the taxonomies in the array … … 689 703 $label_lc = mb_strtolower($taxonomy->label, 'UTF-8'); 690 704 ?> 691 <h2><?php echo mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8'); ?></h2>705 <h2><?php echo esc_html(mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8')); ?></h2> 692 706 <table class="form-table"> 693 707 <?php … … 696 710 '6', 697 711 false, 712 /* translators: %s: Taxonomy name*/ 698 713 sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt') . $overridden['Htax_' . $taxonomy->name . '_template'], $label_lc), 699 714 $overridden_style['Htax_' . $taxonomy->name . '_template']); … … 702 717 '4', 703 718 false, 719 /* translators: %s: Taxonomy name */ 704 720 sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt') . $overridden['Htax_' . $taxonomy->name . '_template_no_anchor'], $label_lc), 705 721 $overridden_style['Htax_' . $taxonomy->name . '_template_no_anchor']); … … 711 727 </fieldset> 712 728 <fieldset id="miscellaneous" class="bcn_options"> 713 <legend class="screen-reader-text" data-title="<?php _e( 'The settings for author and date archives, searches, and 404 pages are located under this tab.', 'breadcrumb-navxt' );?>"><?php_e( 'Miscellaneous', 'breadcrumb-navxt' ); ?></legend>714 <h2><?php _e('Author Archives', 'breadcrumb-navxt'); ?></h2>729 <legend class="screen-reader-text" data-title="<?php esc_attr_e( 'The settings for author and date archives, searches, and 404 pages are located under this tab.', 'breadcrumb-navxt' );?>"><?php esc_html_e( 'Miscellaneous', 'breadcrumb-navxt' ); ?></legend> 730 <h2><?php esc_html_e('Author Archives', 'breadcrumb-navxt'); ?></h2> 715 731 <table class="form-table"> 716 732 <?php … … 737 753 <tr valign="top"> 738 754 <th scope="row"> 739 <label for="<?php echo $optid;?>"><?php esc_html_e('Author Root Page', 'breadcrumb-navxt');?></label>755 <label for="<?php echo esc_attr($optid);?>"><?php esc_html_e('Author Root Page', 'breadcrumb-navxt');?></label> 740 756 </th> 741 757 <td> 742 758 <?php wp_dropdown_pages(array( 743 759 'name' => $this->unique_prefix . '_options[aauthor_root]', 744 'id' => $optid,760 'id' => esc_attr($optid), 745 761 'echo' => 1, 746 'show_option_none' => __( '— Select —'),762 'show_option_none' => esc_attr__('— Select —', 'breadcrumb-navxt'), 747 763 'option_none_value' => '0', 748 764 'selected' => $this->settings['aauthor_root']->get_value(), … … 751 767 if(isset($overridden['aauthor_root']) && $overridden['aauthor_root'] !== '') 752 768 { 753 printf('<p class="description">%s</p>', $overridden['aauthor_root']);769 printf('<p class="description">%s</p>', esc_html($overridden['aauthor_root'])); 754 770 } 755 771 ?> … … 757 773 </tr> 758 774 </table> 759 <h2><?php _e('Miscellaneous', 'breadcrumb-navxt'); ?></h2>775 <h2><?php esc_html_e('Miscellaneous', 'breadcrumb-navxt'); ?></h2> 760 776 <table class="form-table"> 761 777 <?php … … 797 813 ?> 798 814 </table> 799 <h2><?php _e('Deprecated', 'breadcrumb-navxt'); ?></h2>800 <table class="form-table">801 <tr valign="top">802 <th scope="row">803 <?php esc_html_e('Title Length', 'breadcrumb-navxt'); ?>804 </th>805 <td>806 <label>807 <input name="bcn_options[blimit_title]" type="checkbox" id="blimit_title" value="true" class="disabled" <?php checked(true, $this->settings['blimit_title']->get_value()); ?> />808 <?php printf(esc_html__('Limit the length of the breadcrumb title. (Deprecated, %suse CSS instead%s)', 'breadcrumb-navxt'), '<a title="' . esc_attr__('Go to the guide on trimming breadcrumb title lengths with CSS', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/guides/trimming-breadcrumb-title-lengths-with-css/">', '</a>');?>809 </label><br />810 <ul>811 <li>812 <label for="amax_title_length">813 <?php esc_html_e('Max Title Length: ','breadcrumb-navxt');?>814 <input type="number" name="bcn_options[amax_title_length]" id="amax_title_length" min="1" step="1" value="<?php echo esc_html($this->settings['amax_title_length']->get_value(), ENT_COMPAT, 'UTF-8'); ?>" class="small-text disabled" />815 </label>816 </li>817 </ul>818 </td>819 </tr>820 </table>821 815 <?php do_action($this->unique_prefix . '_after_settings_tab_miscellaneous', $this->settings); ?> 822 816 </fieldset> 823 817 <?php do_action($this->unique_prefix . '_after_settings_tabs', $this->settings); ?> 824 818 </div> 825 <p class="submit"><input type="submit" class="button-primary" name="bcn_admin_options" value="<?php esc_attr_e('Save Changes' ) ?>" /></p>819 <p class="submit"><input type="submit" class="button-primary" name="bcn_admin_options" value="<?php esc_attr_e('Save Changes', 'breadcrumb-navxt') ?>" /></p> 826 820 </form> 827 821 </div> -
breadcrumb-navxt/trunk/class.bcn_breadcrumb.php
r3411622 r3425008 35 35 //The corresponding resource ID 36 36 protected $id = null; 37 private $_title = null;38 37 //The type of this breadcrumb 39 38 protected $type; … … 72 71 else 73 72 { 74 $this->template_no_anchor = $this-> run_template_kses(apply_filters('bcn_breadcrumb_template_no_anchor', $template, $this->type, $this->id));73 $this->template_no_anchor = $this->kses(apply_filters('bcn_breadcrumb_template_no_anchor', $template, $this->type, $this->id)); 75 74 $this->set_template(bcn_breadcrumb::get_default_template()); 76 75 } … … 97 96 //Set the title 98 97 $this->title = apply_filters('bcn_breadcrumb_title', $title, $this->type, $this->id); 99 $this->_title = $this->title;100 98 } 101 99 /** … … 149 147 * A wrapper for wp_kses which handles getting the allowed html 150 148 * 151 * @param string $ template_str The template string to run through kses152 * @return string The templatestring post cleaning153 */ 154 protected function run_template_kses($template_str)155 { 156 return wp_kses($ template_str, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post')));149 * @param string $string The string to run through kses 150 * @return string The string post cleaning 151 */ 152 protected function kses($string) 153 { 154 return wp_kses($string, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post'))); 157 155 } 158 156 /** … … 164 162 { 165 163 //Assign the breadcrumb template 166 $this->template = $this-> run_template_kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id));164 $this->template = $this->kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id)); 167 165 } 168 166 /** … … 223 221 //Build our replacements array 224 222 $replacements = array( 225 '%title%' => esc_attr( strip_tags($this->title)),223 '%title%' => esc_attr(wp_strip_all_tags($this->title)), 226 224 '%link%' => esc_url($this->url), 227 '%htitle%' => $this-> title,225 '%htitle%' => $this->kses($this->title), /*TODO: verify if we want to restrict this more*/ 228 226 '%type%' => apply_filters('bcn_breadcrumb_types', $this->type, $this->id), 229 '%ftitle%' => esc_attr( strip_tags($this->_title)),230 '%fhtitle%' => $this-> _title,231 '%position%' => $position,227 '%ftitle%' => esc_attr(wp_strip_all_tags($this->title)), 228 '%fhtitle%' => $this->kses($this->title), /*TODO: verify if we want to restrict this more*/ 229 '%position%' => esc_attr($position), 232 230 'bcn-aria-current' => $aria_current_str 233 231 ); … … 240 238 else 241 239 { 242 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('bcn_breadcrumb::type must be an array', 'breadcrumb-navxt'), '6.0.2'); 240 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('bcn_breadcrumb::type must be an array', 'breadcrumb-navxt'), '6.0.2'); 241 //Type wasn't an array, throw it through esc_attr 242 $replacements['%type%'] == esc_attr($replacements['%type%']); 243 243 } 244 244 $replacements = apply_filters('bcn_template_tags', $replacements, $this->type, $this->id); -
breadcrumb-navxt/trunk/class.bcn_breadcrumb_trail.php
r3411622 r3425008 31 31 public function __construct() 32 32 { 33 //@see https://core.trac.wordpress.org/ticket/1052734 if(!is_textdomain_loaded('breadcrumb-navxt'))35 {36 load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages');37 }38 33 $this->trail = &$this->breadcrumbs; 39 34 //Initialize with default option values … … 80 75 //Paged options 81 76 //The template for paged breadcrumb 77 /* translators: %htitle%: The page title which may contain HTML, in this case it should be a number as it is when on a paginated archive */ 82 78 'Hpaged_template' => sprintf('<span class="%%type%%">%1$s</span>', esc_attr__('Page %htitle%', 'breadcrumb-navxt')), 83 79 //Should we try filling out paged information … … 121 117 //The breadcrumb template for search breadcrumbs 122 118 'Hsearch_template' => sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>', 119 /* translators: %1$s: The searched phrase */ 123 120 sprintf(esc_attr__('Search results for '%1$s'', 'breadcrumb-navxt'), 121 /* translators: %title%: The searched phrase */ 124 122 sprintf('<a property="item" typeof="WebPage" title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of search results for %title%.', 'breadcrumb-navxt')))), 125 123 //The breadcrumb template for search breadcrumbs, used when an anchor is not necessary 126 124 'Hsearch_template_no_anchor' => sprintf('<span class="%%type%%">%1$s</span>', 125 /* translators: %1$s: The searched phrase */ 127 126 sprintf(esc_attr__('Search results for '%1$s'', 'breadcrumb-navxt'), '%htitle%')), 128 127 //Tag related stuff … … 139 138 //The anchor template for author breadcrumbs 140 139 'Hauthor_template' => sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>', 140 /* translators: %1$s: The post author name the current archive is for */ 141 141 sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), 142 142 sprintf('<a title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current>%%htitle%%</a>', esc_attr__('Go to the first page of posts by %title%.', 'breadcrumb-navxt')))), 143 143 //The anchor template for author breadcrumbs, used when anchors are not needed 144 144 'Hauthor_template_no_anchor' => sprintf('<span class="%%type%%">%1$s</span>', 145 /* translators: %1$s: The post author name the current archive is for */ 145 146 sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')), 146 147 //Which of the various WordPress display types should the author breadcrumb display … … 519 520 if(!($post instanceof WP_Post)) 520 521 { 521 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$post global is not of type WP_Post', 'breadcrumb-navxt'), '5.1.1');522 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('$post global is not of type WP_Post', 'breadcrumb-navxt'), '5.1.1'); 522 523 return; 523 524 } … … 574 575 if(!($term instanceof WP_Term)) 575 576 { 576 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$term global is not of type WP_Term', 'breadcrumb-navxt'), '7.0.3');577 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('$term global is not of type WP_Term', 'breadcrumb-navxt'), '7.0.3'); 577 578 return; 578 579 } … … 1228 1229 $this->order($reverse); 1229 1230 //The main compiling loop 1230 $trail_str = $this->display_loop($this->breadcrumbs, $linked, $reverse, $template, $outer_template, $this->opt['hseparator']);1231 return $trail_str ;1231 $trail_str_escaped = $this->display_loop($this->breadcrumbs, $linked, $reverse, $template, $outer_template, $this->opt['hseparator']); 1232 return $trail_str_escaped; 1232 1233 } 1233 1234 /** … … 1254 1255 } 1255 1256 //Initialize the string which will hold the assembled trail 1256 $trail_str = '';1257 $trail_str_escaped = ''; 1257 1258 foreach($breadcrumbs as $key => $breadcrumb) 1258 1259 { … … 1264 1265 if(is_array($breadcrumb)) 1265 1266 { 1266 $trail_str .= sprintf($outer_template,1267 $trail_str_escaped .= sprintf($outer_template, 1267 1268 $this->display_loop($breadcrumb, $linked, $reverse, $template, $outer_template, $this->opt['hseparator_higher_dim'], $depth + 1), $separator); 1268 1269 } … … 1280 1281 $attribs .= sprintf(' %1$s="%2$s"', esc_attr($attrib), esc_attr(implode(' ', $value))); 1281 1282 } 1282 //Filter li_attributes adding attributes to the li element 1283 //TODO: Remove the bcn_li_attributes filter 1284 $attribs = apply_filters_deprecated('bcn_li_attributes', array($attribs, $breadcrumb->get_types(), $breadcrumb->get_id()), '6.0.0', 'bcn_display_attributes'); 1285 //TODO: Deprecate this filter in favor of just using bcn_display_attributes_array 1286 $attribs = apply_filters('bcn_display_attributes', $attribs, $breadcrumb->get_types(), $breadcrumb->get_id()); 1283 //TODO: Remove this filter in favor of just using bcn_display_attributes_array 1284 $attribs = apply_filters_deprecated('bcn_display_attributes', array($attribs, $breadcrumb->get_types(), $breadcrumb->get_id()), '7.5.1', 'bcn_display_attribute_array'); 1287 1285 $separator = apply_filters('bcn_display_separator', $separator, $position, $last_position, $depth); 1288 1286 //Assemble the breadcrumb 1289 $trail_str .= sprintf($template, $breadcrumb->assemble($linked, $position, ($key === 0)), $separator, $attribs);1287 $trail_str_escaped .= sprintf($template, $breadcrumb->assemble($linked, $position, ($key === 0)), wp_kses($separator, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post'))), $attribs); 1290 1288 } 1291 1289 if($reverse) … … 1298 1296 } 1299 1297 } 1300 return $trail_str ;1298 return $trail_str_escaped; 1301 1299 } 1302 1300 /** … … 1312 1310 //Set trail order based on reverse flag 1313 1311 $this->order($reverse); 1314 $trail_str = (object)array(1312 $trail_str_escaped = (object)array( 1315 1313 '@context' => 'http://schema.org', 1316 1314 '@type' => 'BreadcrumbList', 1317 1315 'itemListElement' => $this->json_ld_loop($reverse)); 1318 return $trail_str ;1316 return $trail_str_escaped; 1319 1317 } 1320 1318 /** … … 1331 1329 $position = count($this->breadcrumbs); 1332 1330 } 1333 $breadcrumbs = array();1331 $breadcrumbs_escaped= array(); 1334 1332 //Loop around our breadcrumbs, call the JSON-LD assembler 1335 1333 foreach($this->breadcrumbs as $breadcrumb) 1336 1334 { 1337 $breadcrumbs [] = $breadcrumb->assemble_json_ld($position);1335 $breadcrumbs_escaped[] = $breadcrumb->assemble_json_ld($position); 1338 1336 if($reverse) 1339 1337 { … … 1345 1343 } 1346 1344 } 1347 return $breadcrumbs ;1345 return $breadcrumbs_escaped; 1348 1346 } 1349 1347 /** -
breadcrumb-navxt/trunk/class.bcn_network_admin.php
r3411622 r3425008 38 38 * @param string $basename The basename of the plugin 39 39 */ 40 function __construct(array &$opts, $basename, array &$settings)40 public function __construct(array &$opts, $basename, array &$settings) 41 41 { 42 42 //We're going to make sure we load the parent's constructor … … 49 49 add_action('network_admin_menu', array($this, 'add_page')); 50 50 } 51 function is_network_admin()51 public function is_network_admin() 52 52 { 53 53 return true; … … 61 61 * @return void 62 62 */ 63 function init()63 public function init() 64 64 { 65 65 //We're going to make sure we run the parent's version of this function as well 66 66 parent::init(); 67 67 } 68 function wp_loaded()68 public function wp_loaded() 69 69 { 70 70 parent::wp_loaded(); … … 73 73 * Return the URL of the settings page for the plugin 74 74 */ 75 function admin_url()75 public function admin_url() 76 76 { 77 77 return admin_url('network/settings.php?page=' . $this->identifier); … … 80 80 * Adds the adminpage the menu and the nice little settings link 81 81 */ 82 function add_page()82 public function add_page() 83 83 { 84 84 //Add the submenu page to "settings" menu … … 103 103 * 104 104 */ 105 function help()105 public function help() 106 106 { 107 107 $screen = get_current_screen(); … … 123 123 * @return mixed The value of the option 124 124 */ 125 function get_option($option)125 public function get_option($option) 126 126 { 127 127 return get_site_option($option); … … 134 134 * 135 135 */ 136 function update_option($option, $newvalue, $autoload = null)136 public function update_option($option, $newvalue, $autoload = null) 137 137 { 138 138 return update_site_option($option, $newvalue); … … 147 147 * 148 148 */ 149 function add_option($option, $value = '', $deprecated = '', $autoload = 'yes')149 public function add_option($option, $value = '', $deprecated = '', $autoload = 'yes') 150 150 { 151 151 return add_site_option($option, $value); … … 156 156 * @param string $option The name of the option to delete 157 157 */ 158 function delete_option($option)158 public function delete_option($option) 159 159 { 160 160 return delete_site_option($option); … … 163 163 * A message function that checks for the BCN_SETTINGS_* define statement 164 164 */ 165 function multisite_settings_warn()165 public function multisite_settings_warn() 166 166 { 167 167 if(is_multisite()) … … 194 194 * A message function that checks for deprecated settings that are set and warns the user 195 195 */ 196 function deprecated_settings_warn()196 public function deprecated_settings_warn() 197 197 { 198 198 parent::deprecated_settings_warn(); … … 203 203 * @return boool Whether or not the blog options should be disabled 204 204 */ 205 function maybe_disable_blog_options()205 public function maybe_disable_blog_options() 206 206 { 207 207 return false; … … 212 212 * @return bool Whether or not the mainsite options should be disabled 213 213 */ 214 function maybe_disable_mainsite_options()214 public function maybe_disable_mainsite_options() 215 215 { 216 216 return false; -
breadcrumb-navxt/trunk/class.bcn_rest_controller.php
r3411622 r3425008 24 24 function bcn_phpold() 25 25 { 26 printf('<div class="notice notice-error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.3.0'); 26 /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */ 27 printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0'); 27 28 } 28 29 //If we are in the admin, let's print a warning then return -
breadcrumb-navxt/trunk/class.bcn_widget.php
r3411622 r3425008 28 28 //Filter allowed_html array to allow others to add acceptable tags 29 29 $this->allowed_html = apply_filters('bcn_allowed_html', wp_kses_allowed_html('post')); 30 //@see https://core.trac.wordpress.org/ticket/1052731 if(!is_textdomain_loaded('breadcrumb-navxt'))32 {33 load_plugin_textdomain('breadcrumb-navxt', false, 'breadcrumb-navxt/languages');34 }35 30 $ops = array('classname' => 'widget_breadcrumb_navxt', 'description' => __('Adds a breadcrumb trail to your sidebar', 'breadcrumb-navxt')); 36 31 parent::__construct('bcn_widget', 'Breadcrumb NavXT', $ops); … … 52 47 } 53 48 //Mandatory before widget junk 54 echo $args['before_widget'];49 echo wp_kses($args['before_widget'], wp_kses_allowed_html('post')); 55 50 if(!empty($title)) 56 51 { 57 echo $args['before_title'] . $title . $args['after_title'];52 echo wp_kses($args['before_title'], wp_kses_allowed_html('post')) . esc_html($title) . wp_kses($args['after_title'], wp_kses_allowed_html('post')); 58 53 } 59 54 //We'll want to switch between the two breadcrumb output types … … 99 94 } 100 95 //Mandatory after widget junk 101 echo $args['after_widget'];96 echo wp_kses($args['after_widget'], wp_kses_allowed_html('post'));; 102 97 } 103 98 function update($new_instance, $old_instance) 104 99 { 105 100 //Filter out anything that could be invalid 106 $old_instance['title'] = strip_tags($new_instance['title']);101 $old_instance['title'] = wp_strip_all_tags($new_instance['title']); 107 102 $old_instance['pretext'] = wp_kses($new_instance['pretext'], $this->allowed_html); 108 $old_instance['type'] = strip_tags($new_instance['type']);103 $old_instance['type'] = wp_strip_all_tags($new_instance['type']); 109 104 //Have to check more than if it is set as it appears this must effectively run twice since WordPress 5.8 110 105 $old_instance['linked'] = isset($new_instance['linked']) && $new_instance['linked'] !== false; … … 119 114 ?> 120 115 <p> 121 <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"> <?php _e('Title:', 'breadcrumb-navxt'); ?></label>116 <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"> <?php esc_html_e('Title:', 'breadcrumb-navxt'); ?></label> 122 117 <input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('title')); ?>" id="<?php echo esc_attr($this->get_field_id('title')); ?>" value="<?php echo esc_attr($instance['title']);?>" /> 123 118 </p> 124 119 <p> 125 <label for="<?php echo esc_attr($this->get_field_id('pretext')); ?>"> <?php _e('Text to show before the trail:', 'breadcrumb-navxt'); ?></label>120 <label for="<?php echo esc_attr($this->get_field_id('pretext')); ?>"> <?php esc_html_e('Text to show before the trail:', 'breadcrumb-navxt'); ?></label> 126 121 <input class="widefat" type="text" name="<?php echo esc_attr($this->get_field_name('pretext')); ?>" id="<?php echo esc_attr($this->get_field_id('pretext')); ?>" value="<?php echo esc_attr($instance['pretext']);?>" /> 127 122 </p> 128 123 <p> 129 <label for="<?php echo esc_attr($this->get_field_id('type')); ?>"> <?php _e('Output trail as:', 'breadcrumb-navxt'); ?></label>124 <label for="<?php echo esc_attr($this->get_field_id('type')); ?>"> <?php esc_html_e('Output trail as:', 'breadcrumb-navxt'); ?></label> 130 125 <select name="<?php echo esc_attr($this->get_field_name('type')); ?>" id="<?php echo esc_attr($this->get_field_id('type')); ?>"> 131 <option value="list" <?php selected('list', $instance['type']);?>><?php _e('List', 'breadcrumb-navxt'); ?></option>132 <option value="microdata" <?php selected('microdata', $instance['type']);?>><?php _e('Schema.org BreadcrumbList (RDFa)', 'breadcrumb-navxt'); ?></option>133 <option value="microdata_wai_aria" <?php selected('microdata_wai_aria', $instance['type']);?>><?php _e('Schema.org BreadcrumbList (RDFa) with WAI-ARIA', 'breadcrumb-navxt'); ?></option>134 <option value="breadcrumblist_microdata" <?php selected('breadcrumblist_microdata', $instance['type']);?>><?php _e('Schema.org BreadcrumbList (microdata)', 'breadcrumb-navxt'); ?></option>135 <option value="plain" <?php selected('plain', $instance['type']);?>><?php _e('Plain', 'breadcrumb-navxt'); ?></option>126 <option value="list" <?php selected('list', $instance['type']);?>><?php esc_html_e('List', 'breadcrumb-navxt'); ?></option> 127 <option value="microdata" <?php selected('microdata', $instance['type']);?>><?php esc_html_e('Schema.org BreadcrumbList (RDFa)', 'breadcrumb-navxt'); ?></option> 128 <option value="microdata_wai_aria" <?php selected('microdata_wai_aria', $instance['type']);?>><?php esc_html_e('Schema.org BreadcrumbList (RDFa) with WAI-ARIA', 'breadcrumb-navxt'); ?></option> 129 <option value="breadcrumblist_microdata" <?php selected('breadcrumblist_microdata', $instance['type']);?>><?php esc_html_e('Schema.org BreadcrumbList (microdata)', 'breadcrumb-navxt'); ?></option> 130 <option value="plain" <?php selected('plain', $instance['type']);?>><?php esc_html_e('Plain', 'breadcrumb-navxt'); ?></option> 136 131 <?php do_action('bcn_widget_display_types', $instance);?> 137 132 </select> … … 139 134 <p> 140 135 <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('linked')); ?>" id="<?php echo esc_attr($this->get_field_id('linked')); ?>"<?php checked(true, $instance['linked']);?> /> 141 <label for="<?php echo esc_attr($this->get_field_id('linked')); ?>"> <?php _e('Link the breadcrumbs', 'breadcrumb-navxt'); ?></label><br />136 <label for="<?php echo esc_attr($this->get_field_id('linked')); ?>"> <?php esc_html_e('Link the breadcrumbs', 'breadcrumb-navxt'); ?></label><br /> 142 137 <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('reverse')); ?>" id="<?php echo esc_attr($this->get_field_id('reverse')); ?>"<?php checked(true, $instance['reverse']);?> /> 143 <label for="<?php echo esc_attr($this->get_field_id('reverse')); ?>"> <?php _e('Reverse the order of the trail', 'breadcrumb-navxt'); ?></label><br />138 <label for="<?php echo esc_attr($this->get_field_id('reverse')); ?>"> <?php esc_html_e('Reverse the order of the trail', 'breadcrumb-navxt'); ?></label><br /> 144 139 <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('front')); ?>" id="<?php echo esc_attr($this->get_field_id('front')); ?>"<?php checked(true, $instance['front']);?> /> 145 <label for="<?php echo esc_attr($this->get_field_id('front')); ?>"> <?php _e('Hide the trail on the front page', 'breadcrumb-navxt'); ?></label><br />140 <label for="<?php echo esc_attr($this->get_field_id('front')); ?>"> <?php esc_html_e('Hide the trail on the front page', 'breadcrumb-navxt'); ?></label><br /> 146 141 <input class="checkbox" type="checkbox" name="<?php echo esc_attr($this->get_field_name('force')); ?>" id="<?php echo esc_attr($this->get_field_id('force')); ?>"<?php checked(true, $instance['force']);?> /> 147 <label for="<?php echo esc_attr($this->get_field_id('force')); ?>"> <?php _e('Ignore breadcrumb cache', 'breadcrumb-navxt'); ?></label><br />142 <label for="<?php echo esc_attr($this->get_field_id('force')); ?>"> <?php esc_html_e('Ignore breadcrumb cache', 'breadcrumb-navxt'); ?></label><br /> 148 143 </p> 149 144 <?php -
breadcrumb-navxt/trunk/includes/adminKit/class-mtekk_adminkit.php
r3411622 r3425008 89 89 abstract class adminKit 90 90 { 91 const version = '3.1. 1';91 const version = '3.1.2'; 92 92 protected $full_name; 93 93 protected $short_name; … … 103 103 protected $settings = array(); 104 104 protected $form; 105 function __construct()105 public function __construct() 106 106 { 107 107 $this->message = array(); … … 113 113 //Installation Script hook 114 114 add_action('activate_' . $this->plugin_basename, array($this, 'install')); 115 //Initializes l10n domain116 $this->local();117 115 add_action('wp_loaded', array($this, 'wp_loaded')); 118 116 $this->form = new form($this->unique_prefix); … … 120 118 //add_action('add_screen_help_and_options', array($this, 'help')); 121 119 } 122 function wp_loaded()120 public function wp_loaded() 123 121 { 124 122 //Filter our allowed html tags … … 128 126 * Returns the internal mtekk_admin_class version 129 127 */ 130 function get_admin_class_version()128 public function get_admin_class_version() 131 129 { 132 130 return adminKit::version; … … 135 133 * Checks if the administrator has the access capability, and adds it if they don't 136 134 */ 137 function add_cap()135 public function add_cap() 138 136 { 139 137 $role = get_role('administrator'); … … 146 144 * Return the URL of the settings page for the plugin 147 145 */ 148 function admin_url()146 public function admin_url() 149 147 { 150 148 return admin_url('options-general.php?page=' . $this->identifier); … … 158 156 * @return string the assembled anchor 159 157 */ 160 function admin_anchor($mode, $title = '', $text = '')158 public function admin_anchor($mode, $title = '', $text = '') 161 159 { 162 160 return $this->nonced_anchor($this->admin_url(), 'admin_' . $mode, 'true', $title, $text); … … 173 171 * @return string the assembled anchor 174 172 */ 175 function nonced_anchor($uri, $mode, $value = 'true', $title = '', $text = '', $anchor_extras = '')173 public function nonced_anchor($uri, $mode, $value = 'true', $title = '', $text = '', $anchor_extras = '') 176 174 { 177 175 //Assemble our url, nonce and all 178 176 $url = wp_nonce_url(add_query_arg($this->unique_prefix . '_' . $mode, $value, $uri), $this->unique_prefix . '_' . $mode); 179 177 //Return a valid anchor 180 return ' <a title="' . esc_attr($title) . '" href="' . $url. '" '. $anchor_extras . '>' . esc_html($text) . '</a>';178 return ' <a title="' . esc_attr($title) . '" href="' . esc_url($url) . '" '. $anchor_extras . '>' . esc_html($text) . '</a>'; 181 179 } 182 180 /** … … 185 183 * @param string $mode The specific nonce "mode" (see nonced_anchor) that is being checked 186 184 */ 187 function check_nonce($mode)188 { 189 check_admin_referer($this->unique_prefix . '_' . $mode);185 public function check_nonce($mode) 186 { 187 return check_admin_referer($this->unique_prefix . '_' . $mode); 190 188 } 191 189 /** 192 190 * Makes sure the current user can manage options to proceed 193 191 */ 194 function security()192 protected function security() 195 193 { 196 194 //If the user can not manage options we will die on them 197 195 if(!current_user_can($this->access_level)) 198 196 { 199 wp_die( __('Insufficient privileges to proceed.', $this->identifier));200 } 201 } 202 function init()197 wp_die(esc_html__('Insufficient privileges to proceed.', $this->identifier)); 198 } 199 } 200 public function init() 203 201 { 204 202 $this->add_cap(); … … 262 260 wp_register_script('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.js', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.js'), array('jquery-ui-tabs'), self::version, true); 263 261 //Register CSS for tabs 264 wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.css', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.css') );262 wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.css', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.css'), array(), self::version); 265 263 //Register options 266 264 register_setting($this->unique_prefix . '_options', $this->unique_prefix . '_options', ''); … … 273 271 * TODO: make this more generic for easier extension 274 272 */ 275 function add_page()273 public function add_page() 276 274 { 277 275 //Add the submenu page to "settings" menu … … 291 289 } 292 290 /** 293 * Initializes localization textdomain for translations (if applicable)294 *295 * Will conditionally load the textdomain for translations. This is here for296 * plugins that span multiple files and have localization in more than one file297 *298 * @return void299 */300 function local()301 {302 global $l10n;303 // the global and the check might become obsolete in304 // further wordpress versions305 // @see https://core.trac.wordpress.org/ticket/10527306 if(!isset($l10n[$this->identifier]))307 {308 load_plugin_textdomain($this->identifier, false, $this->identifier . '/languages');309 }310 }311 /**312 291 * Places in a link to the settings page in the plugins listing entry 313 292 * … … 316 295 * @return array Array of links that are output in the listing. 317 296 */ 318 function filter_plugin_actions($links, $file)297 public function filter_plugin_actions($links, $file) 319 298 { 320 299 //Make sure we are adding only for the current plugin … … 322 301 { 323 302 //Add our link to the end of the array to better integrate into the WP 2.8 plugins page 324 $links[] = '<a href="' . $this->admin_url() . '">' . esc_html__('Settings') . '</a>';303 $links[] = '<a href="' . esc_url($this->admin_url()) . '">' . esc_html__('Settings', $this->identifier) . '</a>'; 325 304 } 326 305 return $links; … … 331 310 * @return bool whether or not the plugin has been installed 332 311 */ 333 function is_installed()312 public function is_installed() 334 313 { 335 314 $opts = $this->get_option($this->unique_prefix . '_options'); … … 341 320 * FIXME: seems there is a lot of very similar code in opts_upgrade_wrapper 342 321 */ 343 function install()322 public function install() 344 323 { 345 324 //Call our little security function … … 374 353 * This removes database settings upon deletion of the plugin from WordPress 375 354 */ 376 function uninstall()355 public function uninstall() 377 356 { 378 357 //Remove the option array setting … … 387 366 * TODO: change this to being auto called in admin_init action 388 367 */ 389 function version_check($version)368 public function version_check($version) 390 369 { 391 370 //If we didn't get a version, setup … … 441 420 * @return boolean 442 421 */ 443 function settings_validate(array &$settings)422 public function settings_validate(array &$settings) 444 423 { 445 424 foreach($settings as $setting) … … 452 431 } 453 432 } 454 else if($setting instanceof setting && $setting->get_value() !== $setting->validate($setting->get_value())) 433 else if($setting instanceof setting && $setting->get_value() !== $setting->validate($setting->get_value())) //FIXME: not sure I like this 455 434 { 456 435 return false; 457 436 } 458 437 } 459 return true; 438 return true; //FIXME: Shouldn't the default to be false? 460 439 } 461 440 /** 462 441 * Synchronizes the backup options entry with the current options entry 463 442 */ 464 function opts_backup()443 protected function opts_backup() 465 444 { 466 445 //Set the backup options in the DB to the current options … … 599 578 * @return number 600 579 */ 601 function setting_equal_check($a, $b)580 public function setting_equal_check($a, $b) 602 581 { 603 582 if(is_array($a) || is_array($b)) … … 641 620 } 642 621 /** 643 * Generates array of the new non-default settings based off of form input622 * Generates array of the new non-default settings based off of form $input 644 623 * 645 624 * @param array $input The form input array of setting values … … 668 647 * 4) Save to database the difference generated in #4 669 648 */ 670 function opts_update()649 protected function opts_update() 671 650 { 672 651 //Do some security related things as we are not using the normal WP settings API … … 680 659 $this->update_option($this->unique_prefix . '_options_bk', $this->opt, false); 681 660 $opt_prev = $this->opt; 661 //While this should never happen, if the settings are missing, exit early 662 if(!isset($_POST[$this->unique_prefix . '_options'])) 663 { 664 return; 665 } 682 666 //Grab our incoming array (the data is dirty) 683 667 $input = $_POST[$this->unique_prefix . '_options']; … … 714 698 $temp .= '<br />' . $setting; 715 699 } 716 $this->messages[] = new message($temp . '<br />' . sprintf(esc_html__('Please include this message in your %sbug report%s.', $this->identifier), '<a title="' . sprintf(esc_attr__('Go to the %s support forum.', $this->identifier), $this->short_name) . '" href="' . $this->support_url . '">', '</a>'), 'info'); 700 /* translators: %1$s: HTML opening tag for link to the support forums, %2$s: HTML closing tag for link to support forums */ 701 $this->messages[] = new message($temp . '<br />' . sprintf(esc_html__('Please include this message in your %1$sbug report%2$s.', $this->identifier), '<a title="' . sprintf(esc_attr__('Go to the %s support forum.', $this->identifier), $this->short_name) . '" href="' . $this->support_url . '">', '</a>'), 'info'); 717 702 } 718 703 add_action('admin_notices', array($this, 'messages')); … … 721 706 * Retrieves the settings from database and exports as JSON 722 707 */ 723 function settings_export() 724 { 708 public function settings_export() 709 { 710 //Check if the user has permissions to do this 711 $this->security(); 725 712 //Do a nonce check, prevent malicious link/form problems 726 check_admin_referer($this->unique_prefix . '_admin_import_export'); 727 //Must clone the defaults since PHP normally shallow copies 728 $default_settings = array_map('mtekk\adminKit\adminKit::setting_cloner', $this->settings); 729 //Get the database options, and load 730 //FIXME: This changes once we save settings to the db instead of opts 731 adminKit::load_opts_into_settings($this->get_option($this->unique_prefix . '_options'), $this->settings); 732 //Get the unique settings 733 $export_settings = apply_filters($this->unique_prefix . '_settings_to_export', array_udiff_assoc($this->settings, $default_settings, array($this, 'setting_equal_check'))); 734 //Change our header to application/json for direct save 735 header('Cache-Control: public'); 736 //The next two will cause good browsers to download instead of displaying the file 737 header('Content-Description: File Transfer'); 738 header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.json'); 739 header('Content-Type: application/json'); 740 //JSON encode our settings array 741 $output = json_encode( 742 (object)array( 743 'plugin' => $this->short_name, 744 'version' => $this::version, 745 'settings' => $export_settings) 746 , JSON_UNESCAPED_SLASHES, 32); 747 //Let the browser know how long the file is 748 header('Content-Length: ' . strlen($output)); // binary length 749 //Output the file 750 echo $output; 751 //Prevent WordPress from continuing on 752 die(); 713 if(check_admin_referer($this->unique_prefix . '_admin_import_export')) 714 { 715 //Must clone the defaults since PHP normally shallow copies 716 $default_settings = array_map('mtekk\adminKit\adminKit::setting_cloner', $this->settings); 717 //Get the database options, and load 718 //FIXME: This changes once we save settings to the db instead of opts 719 adminKit::load_opts_into_settings($this->get_option($this->unique_prefix . '_options'), $this->settings); 720 //Get the unique settings 721 $export_settings = apply_filters($this->unique_prefix . '_settings_to_export', array_udiff_assoc($this->settings, $default_settings, array($this, 'setting_equal_check'))); 722 //Change our header to application/json for direct save 723 header('Cache-Control: public'); 724 //The next two will cause good browsers to download instead of displaying the file 725 header('Content-Description: File Transfer'); 726 header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.json'); 727 header('Content-Type: application/json'); 728 //JSON encode our settings array 729 $output_escaped= wp_json_encode( 730 (object)array( 731 'plugin' => $this->short_name, 732 'version' => $this::version, 733 'settings' => $export_settings) 734 , JSON_UNESCAPED_SLASHES, 32); 735 //Let the browser know how long the file is 736 header('Content-Length: ' . strlen($output_escaped)); // binary length 737 //Output the file 738 echo $output_escaped; 739 //Prevent WordPress from continuing on 740 die(); 741 } 753 742 } 754 743 /** 755 744 * Imports JSON settings into database 756 */ 757 function settings_import() 758 { 745 * 746 */ 747 public function settings_import() 748 { 749 //Check if the user has permissions to do this 750 $this->security(); 759 751 //Do a nonce check, prevent malicious link/form problems 760 check_admin_referer($this->unique_prefix . '_admin_import_export'); 761 //Set the backup options in the DB to the current options 762 $this->opts_backup(); 763 //Load the user uploaded file, handle failure gracefully 764 if(is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name'])) 765 { 766 //Grab the json settings from the temp file, treat as associative array so we can just throw the settings subfield at the update loop 767 $settings_upload = json_decode(file_get_contents($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']), true); 768 //Only continue if we have a JSON object that is for this plugin (the the WP rest_is_object() function is handy here as the REST API passes JSON) 769 if(rest_is_object($settings_upload) && isset($settings_upload['plugin']) && $settings_upload['plugin'] === $this->short_name) 770 { 752 if(check_admin_referer($this->unique_prefix . '_admin_import_export')) 753 { 754 //Set the backup options in the DB to the current options 755 $this->opts_backup(); 756 //Load the user uploaded file, handle failure gracefully 757 if(isset($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name'])) 758 { 759 //Grab the json settings from the temp file, treat as associative array so we can just throw the settings subfield at the update loop 760 $settings_upload = json_decode(file_get_contents($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']), true); 761 //Only continue if we have a JSON object that is for this plugin (the the WP rest_is_object() function is handy here as the REST API passes JSON) 762 if(rest_is_object($settings_upload) && isset($settings_upload['plugin']) && $settings_upload['plugin'] === $this->short_name) 763 { 764 //Act as if the JSON file was just a bunch of POST entries for a settings save 765 //Run through the loop and get the diff from defaults 766 //this isn't obvious but calls adminkit::settings_update_loop() which calls setting::maybe_update_from_form_input which performs sanitization on a per setting basis 767 $new_settings = $this->get_settings_diff($settings_upload['settings'], true); 768 //FIXME: Eventually we'll save the object array, but not today 769 //Convert to opts array for saving 770 $this->opt = adminKit::settings_to_opts($new_settings); 771 //Run opts through update script 772 //Make sure we safely import and upgrade settings if needed 773 $this->opts_upgrade($this->opt, $settings_upload['version']); 774 //Commit the option changes 775 $updated = $this->update_option($this->unique_prefix . '_options', $this->opt, true); 776 //Check if known settings match attempted save 777 if($updated && count(array_diff_key($settings_upload['settings'], $this->settings)) == 0) 778 { 779 //Let the user know everything went ok 780 $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier) 781 . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success'); 782 } 783 else 784 { 785 $this->messages[] = new message(esc_html__('No settings were imported. Settings from uploaded file matched existing settings.', $this->identifier), 'info'); 786 } 787 //Output any messages that there may be 788 add_action('admin_notices', array($this, 'messages')); 789 //And return as we're successful 790 return; 791 } 792 //If it wasn't JSON, try XML 793 else 794 { 795 return $this->opts_import(); 796 } 797 } 798 //Throw an error since we could not load the file for various reasons 799 $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error'); 800 } 801 } 802 /** 803 * Exports a XML options document 804 * @deprecated 7.5.0 805 */ 806 public function opts_export() 807 { 808 _deprecated_function( __FUNCTION__, '7.5.0', '\mtekk\adminKit::settings_export'); 809 //Check if the user has permissions to do this 810 $this->security(); 811 //Do a nonce check, prevent malicious link/form problems 812 if(check_admin_referer($this->unique_prefix . '_admin_import_export')) 813 { 814 //Update our internal settings 815 $this->opt = $this->get_option($this->unique_prefix . '_options'); 816 //Create a DOM document 817 $dom = new \DOMDocument('1.0', 'UTF-8'); 818 //Adds in newlines and tabs to the output 819 $dom->formatOutput = true; 820 //We're not using a DTD therefore we need to specify it as a standalone document 821 $dom->xmlStandalone = true; 822 //Add an element called options 823 $node = $dom->createElement('options'); 824 $parnode = $dom->appendChild($node); 825 //Add a child element named plugin 826 $node = $dom->createElement('plugin'); 827 $plugnode = $parnode->appendChild($node); 828 //Add some attributes that identify the plugin and version for the options export 829 $plugnode->setAttribute('name', $this->short_name); 830 $plugnode->setAttribute('version', $this::version); 831 //Change our header to text/xml for direct save 832 header('Cache-Control: public'); 833 //The next two will cause good browsers to download instead of displaying the file 834 header('Content-Description: File Transfer'); 835 header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.xml'); 836 header('Content-Type: text/xml'); 837 //Loop through the options array 838 foreach($this->opt as $key=>$option) 839 { 840 if(is_array($option)) 841 { 842 continue; 843 } 844 //Add a option tag under the options tag, store the option value 845 $node = $dom->createElement('option', htmlentities($option, ENT_COMPAT | ENT_XML1, 'UTF-8')); 846 $newnode = $plugnode->appendChild($node); 847 //Change the tag's name to that of the stored option 848 $newnode->setAttribute('name', $key); 849 } 850 //Prepare the XML for output 851 $output_escaped = $dom->saveXML(); 852 //Let the browser know how long the file is 853 header('Content-Length: ' . strlen($output_escaped)); // binary length 854 //Output the file 855 echo $output_escaped; 856 //Prevent WordPress from continuing on 857 die(); 858 } 859 } 860 /** 861 * Imports a XML options document 862 * 863 * FIXME: Where is the input sanitization/validation? 864 */ 865 public function opts_import() 866 { 867 //Check if the user has permissions to do this 868 $this->security(); 869 //Our quick and dirty error suppressor 870 $error_handler = function($errno, $errstr, $eerfile, $errline, $errcontext) 871 { 872 return true; 873 }; 874 //Do a nonce check, prevent malicious link/form problems 875 if(check_admin_referer($this->unique_prefix . '_admin_import_export')) 876 { 877 //Set the backup options in the DB to the current options 878 $this->opts_backup(); 879 //Create a DOM document 880 $dom = new \DOMDocument('1.0', 'UTF-8'); 881 //We want to catch errors ourselves 882 set_error_handler($error_handler); 883 //Load the user uploaded file, handle failure gracefully 884 if(isset($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && $dom->load($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name'])) 885 { 886 $opts_temp = array(); 887 $version = ''; 888 //Have to use an xpath query otherwise we run into problems 889 $xpath = new \DOMXPath($dom); 890 $option_sets = $xpath->query('plugin'); 891 //Loop through all of the xpath query results 892 foreach($option_sets as $options) 893 { 894 //We only want to import options for only this plugin 895 if($options->getAttribute('name') === $this->short_name) 896 { 897 //Grab the file version 898 $version = $options->getAttribute('version'); 899 //Loop around all of the options 900 foreach($options->getelementsByTagName('option') as $child) 901 { 902 //Place the option into the option array, DOMDocument decodes html entities for us 903 $opts_temp[$child->getAttribute('name')] = $child->nodeValue; 904 } 905 } 906 } 771 907 //Act as if the JSON file was just a bunch of POST entries for a settings save 772 908 //Run through the loop and get the diff from defaults 773 $new_settings = $this->get_settings_diff($settings_upload['settings'], true); 909 //this isn't obvious but calls adminkit::settings_update_loop() which calls setting::maybe_update_from_form_input which performs sanitization on a per setting basis 910 $new_settings = $this->get_settings_diff($opts_temp, true); 774 911 //FIXME: Eventually we'll save the object array, but not today 775 912 //Convert to opts array for saving … … 778 915 //Make sure we safely import and upgrade settings if needed 779 916 $this->opts_upgrade($this->opt, $settings_upload['version']); 780 //Commit the option changes 781 $updated = $this->update_option($this->unique_prefix . '_options', $this->opt, true); 782 //Check if known settings match attempted save 783 if($updated && count(array_diff_key($settings_upload['settings'], $this->settings)) == 0) 784 { 785 //Let the user know everything went ok 786 $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier) 787 . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success'); 788 } 789 else 790 { 791 $this->messages[] = new message(esc_html__('No settings were imported. Settings from uploaded file matched existing settings.', $this->identifier), 'info'); 792 } 793 //Output any messages that there may be 794 add_action('admin_notices', array($this, 'messages')); 795 //And return as we're successful 796 return; 797 } 798 //If it wasn't JSON, try XML 917 918 //Commit the loaded options to the database 919 $this->update_option($this->unique_prefix . '_options', $this->opt, true); 920 //Everything was successful, let the user know 921 $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier) 922 . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success'); 923 } 799 924 else 800 925 { 801 return $this->opts_import(); 802 } 803 } 804 //Throw an error since we could not load the file for various reasons 805 $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error'); 806 } 807 /** 808 * Exports a XML options document 809 * @deprecated 7.5.0 810 */ 811 function opts_export() 812 { 813 _deprecated_function( __FUNCTION__, '7.5.0', '\mtekk\adminKit::settings_export'); 814 //Do a nonce check, prevent malicious link/form problems 815 check_admin_referer($this->unique_prefix . '_admin_import_export'); 816 //Update our internal settings 817 $this->opt = $this->get_option($this->unique_prefix . '_options'); 818 //Create a DOM document 819 $dom = new \DOMDocument('1.0', 'UTF-8'); 820 //Adds in newlines and tabs to the output 821 $dom->formatOutput = true; 822 //We're not using a DTD therefore we need to specify it as a standalone document 823 $dom->xmlStandalone = true; 824 //Add an element called options 825 $node = $dom->createElement('options'); 826 $parnode = $dom->appendChild($node); 827 //Add a child element named plugin 828 $node = $dom->createElement('plugin'); 829 $plugnode = $parnode->appendChild($node); 830 //Add some attributes that identify the plugin and version for the options export 831 $plugnode->setAttribute('name', $this->short_name); 832 $plugnode->setAttribute('version', $this::version); 833 //Change our header to text/xml for direct save 834 header('Cache-Control: public'); 835 //The next two will cause good browsers to download instead of displaying the file 836 header('Content-Description: File Transfer'); 837 header('Content-disposition: attachment; filename=' . $this->unique_prefix . '_settings.xml'); 838 header('Content-Type: text/xml'); 839 //Loop through the options array 840 foreach($this->opt as $key=>$option) 841 { 842 if(is_array($option)) 843 { 844 continue; 845 } 846 //Add a option tag under the options tag, store the option value 847 $node = $dom->createElement('option', htmlentities($option, ENT_COMPAT | ENT_XML1, 'UTF-8')); 848 $newnode = $plugnode->appendChild($node); 849 //Change the tag's name to that of the stored option 850 $newnode->setAttribute('name', $key); 851 } 852 //Prepare the XML for output 853 $output = $dom->saveXML(); 854 //Let the browser know how long the file is 855 header('Content-Length: ' . strlen($output)); // binary length 856 //Output the file 857 echo $output; 858 //Prevent WordPress from continuing on 859 die(); 860 } 861 /** 862 * Imports a XML options document 863 */ 864 function opts_import() 865 { 866 //Our quick and dirty error suppressor 867 $error_handler = function($errno, $errstr, $eerfile, $errline, $errcontext) 868 { 869 return true; 870 }; 926 //Throw an error since we could not load the file for various reasons 927 $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error'); 928 } 929 //Reset to the default error handler after we're done 930 restore_error_handler(); 931 //Output any messages that there may be 932 add_action('admin_notices', array($this, 'messages')); 933 } 934 } 935 /** 936 * Resets the database settings array to the default set in opt 937 */ 938 public function opts_reset() 939 { 940 //Check if the user has permissions to do this 941 $this->security(); 871 942 //Do a nonce check, prevent malicious link/form problems 872 check_admin_referer($this->unique_prefix . '_admin_import_export'); 873 //Set the backup options in the DB to the current options 874 $this->opts_backup(); 875 //Create a DOM document 876 $dom = new \DOMDocument('1.0', 'UTF-8'); 877 //We want to catch errors ourselves 878 set_error_handler($error_handler); 879 //Load the user uploaded file, handle failure gracefully 880 if(is_uploaded_file($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']) && $dom->load($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name'])) 881 { 882 $opts_temp = array(); 883 $version = ''; 884 //Have to use an xpath query otherwise we run into problems 885 $xpath = new \DOMXPath($dom); 886 $option_sets = $xpath->query('plugin'); 887 //Loop through all of the xpath query results 888 foreach($option_sets as $options) 889 { 890 //We only want to import options for only this plugin 891 if($options->getAttribute('name') === $this->short_name) 892 { 893 //Grab the file version 894 $version = $options->getAttribute('version'); 895 //Loop around all of the options 896 foreach($options->getelementsByTagName('option') as $child) 897 { 898 //Place the option into the option array, DOMDocument decodes html entities for us 899 $opts_temp[$child->getAttribute('name')] = $child->nodeValue; 900 } 901 } 902 } 903 //Make sure we safely import and upgrade settings if needed 904 $this->opts_upgrade($opts_temp, $version); 905 //Commit the loaded options to the database 906 $this->update_option($this->unique_prefix . '_options', $this->opt, true); 907 //Everything was successful, let the user know 908 $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier) 909 . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success'); 910 } 911 else 912 { 913 //Throw an error since we could not load the file for various reasons 914 $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error'); 915 } 916 //Reset to the default error handler after we're done 917 restore_error_handler(); 918 //Output any messages that there may be 919 add_action('admin_notices', array($this, 'messages')); 920 } 921 /** 922 * Resets the database settings array to the default set in opt 923 */ 924 function opts_reset() 925 { 943 if(check_admin_referer($this->unique_prefix . '_admin_import_export')) 944 { 945 //Set the backup options in the DB to the current options 946 $this->opts_backup(); 947 //Load in the hard coded default option values 948 $this->update_option($this->unique_prefix . '_options', array(), true); 949 //Reset successful, let the user know 950 $this->messages[] = new message(esc_html__('Settings successfully reset to the default values.', $this->identifier) 951 . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier)), 'success'); 952 add_action('admin_notices', array($this, 'messages')); 953 } 954 } 955 /** 956 * Undos the last settings save/reset/import 957 */ 958 public function opts_undo() 959 { 960 //Check if the user has permissions to do this 961 $this->security(); 926 962 //Do a nonce check, prevent malicious link/form problems 927 check_admin_referer($this->unique_prefix . '_admin_import_export'); 928 //Set the backup options in the DB to the current options 929 $this->opts_backup(); 930 //Load in the hard coded default option values 931 $this->update_option($this->unique_prefix . '_options', array(), true); 932 //Reset successful, let the user know 933 $this->messages[] = new message(esc_html__('Settings successfully reset to the default values.', $this->identifier) 934 . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier)), 'success'); 935 add_action('admin_notices', array($this, 'messages')); 936 } 937 /** 938 * Undos the last settings save/reset/import 939 */ 940 function opts_undo() 941 { 942 //Do a nonce check, prevent malicious link/form problems 943 check_admin_referer($this->unique_prefix . '_admin_undo'); 944 //Set the options array to the current options 945 $opt = $this->get_option($this->unique_prefix . '_options'); 946 //Set the options in the DB to the backup options 947 $this->update_option($this->unique_prefix . '_options', $this->get_option($this->unique_prefix . '_options_bk'), true); 948 //Set the backup options to the undone options 949 $this->update_option($this->unique_prefix . '_options_bk', $opt, false); 950 //Send the success/undo message 951 $this->messages[] = new message(esc_html__('Settings successfully undid the last operation.', $this->identifier) 952 . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier)), 'success'); 953 add_action('admin_notices', array($this, 'messages')); 963 if(check_admin_referer($this->unique_prefix . '_admin_undo')) 964 { 965 //Set the options array to the current options 966 $opt = $this->get_option($this->unique_prefix . '_options'); 967 //Set the options in the DB to the backup options 968 $this->update_option($this->unique_prefix . '_options', $this->get_option($this->unique_prefix . '_options_bk'), true); 969 //Set the backup options to the undone options 970 $this->update_option($this->unique_prefix . '_options_bk', $opt, false); 971 //Send the success/undo message 972 $this->messages[] = new message(esc_html__('Settings successfully undid the last operation.', $this->identifier) 973 . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier)), 'success'); 974 add_action('admin_notices', array($this, 'messages')); 975 } 954 976 } 955 977 /** … … 959 981 * @param string $version the version of the passed in options 960 982 */ 961 function opts_upgrade($opts, $version)983 public function opts_upgrade($opts, $version) 962 984 { 963 985 //We don't support using newer versioned option files in older releases … … 972 994 * FIXME: seems there is a lot of very similar code in install 973 995 */ 974 function opts_upgrade_wrapper() 975 { 996 public function opts_upgrade_wrapper() 997 { 998 //Check if the user has permissions to do this 999 $this->security(); 976 1000 //Do a nonce check, prevent malicious link/form problems 977 check_admin_referer($this->unique_prefix . '_admin_upgrade'); 978 //Grab the database options 979 $opts = $this->get_option($this->unique_prefix . '_options'); 980 if(is_array($opts)) 981 { 982 //Feed the just read options into the upgrade function 983 $this->opts_upgrade($opts, $this->get_option($this->unique_prefix . '_version')); 984 //Always have to update the version 985 $this->update_option($this->unique_prefix . '_version', $this::version, false); 986 //Store the options 987 $this->update_option($this->unique_prefix . '_options', $this->opt, true); 988 //Send the success message 989 $this->messages[] = new message(esc_html__('Settings successfully migrated.', $this->identifier), 'success'); 990 } 991 else 992 { 993 //Run the install script 994 $this->install(); 995 //Send the success message 996 $this->messages[] = new message(esc_html__('Default settings successfully installed.', $this->identifier), 'success'); 997 } 998 add_action('admin_notices', array($this, 'messages')); 1001 if(check_admin_referer($this->unique_prefix . '_admin_upgrade')) 1002 { 1003 //Grab the database options 1004 $opts = $this->get_option($this->unique_prefix . '_options'); 1005 if(is_array($opts)) 1006 { 1007 //Feed the just read options into the upgrade function 1008 $this->opts_upgrade($opts, $this->get_option($this->unique_prefix . '_version')); 1009 //Always have to update the version 1010 $this->update_option($this->unique_prefix . '_version', $this::version, false); 1011 //Store the options 1012 $this->update_option($this->unique_prefix . '_options', $this->opt, true); 1013 //Send the success message 1014 $this->messages[] = new message(esc_html__('Settings successfully migrated.', $this->identifier), 'success'); 1015 } 1016 else 1017 { 1018 //Run the install script 1019 $this->install(); 1020 //Send the success message 1021 $this->messages[] = new message(esc_html__('Default settings successfully installed.', $this->identifier), 'success'); 1022 } 1023 add_action('admin_notices', array($this, 'messages')); 1024 } 999 1025 } 1000 1026 /** … … 1004 1030 * 1005 1031 */ 1006 function help()1032 public function help() 1007 1033 { 1008 1034 $screen = get_current_screen(); … … 1018 1044 } 1019 1045 } 1020 function help_contents(\WP_Screen &$screen)1046 public function help_contents(\WP_Screen &$screen) 1021 1047 { 1022 1048 1023 1049 } 1024 function dismiss_message() 1025 { 1050 //FIXME: There just has to be a better way... 1051 public function dismiss_message() 1052 { 1053 $this->security(); 1026 1054 //Grab the submitted UID 1027 $uid = esc_attr($_POST['uid']);1055 $uid = sanitize_html_class(wp_unslash($_POST['uid'])); 1028 1056 //Create a dummy message, with the discovered UID 1029 1057 $message = new message('', '', true, $uid); … … 1035 1063 * Prints to screen all of the messages stored in the message member variable 1036 1064 */ 1037 function messages()1065 public function messages() 1038 1066 { 1039 1067 foreach($this->messages as $message) … … 1044 1072 if(is_array($this->message) && count($this->message)) 1045 1073 { 1046 _deprecated_function( __FUNCTION__, '2.0.0', __('adminKit::message is deprecated, use new adminkit_messages instead.', $this->identifier) );1074 _deprecated_function( __FUNCTION__, '2.0.0', esc_html__('adminKit::message is deprecated, use new adminkit_messages instead.', $this->identifier) ); 1047 1075 //Loop through our message classes 1048 1076 foreach($this->message as $key => $class) … … 1051 1079 foreach($class as $message) 1052 1080 { 1053 printf('<div class="%s"><p>%s</p></div>', esc_attr($key), $message);1081 printf('<div class="%s"><p>%s</p></div>', esc_attr($key), wp_kses($message, wp_kses_allowed_html('post'))); 1054 1082 } 1055 1083 } … … 1061 1089 * Function prototype to prevent errors 1062 1090 */ 1063 function admin_styles()1091 public function admin_styles() 1064 1092 { 1065 1093 … … 1068 1096 * Function prototype to prevent errors 1069 1097 */ 1070 function admin_scripts()1098 public function admin_scripts() 1071 1099 { 1072 1100 … … 1075 1103 * Function prototype to prevent errors 1076 1104 */ 1077 function admin_head()1105 public function admin_head() 1078 1106 { 1079 1107 … … 1082 1110 * Function prototype to prevent errors 1083 1111 */ 1084 function admin_page()1112 public function admin_page() 1085 1113 { 1086 1114 … … 1112 1140 } 1113 1141 } 1114 function import_form()1142 public function import_form() 1115 1143 { 1116 1144 $form = '<div id="mtekk_admin_import_export_relocate">'; … … 1127 1155 $form .= esc_html__('Select a JSON or XML settings file to upload and import settings from.', $this->identifier); 1128 1156 $form .= '</p></td></tr></table><p class="submit">'; 1129 $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_import" value="%2$s"/>', $this->unique_prefix, esc_attr__('Import', $this->identifier));1130 $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_export" value="%2$s"/>', $this->unique_prefix, esc_attr__('Export', $this->identifier));1131 $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_reset" value="%2$s"/>', $this->unique_prefix, esc_attr__('Reset', $this->identifier));1157 $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_import" value="%2$s"/>', esc_attr($this->unique_prefix), esc_attr__('Import', $this->identifier)); 1158 $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_settings_export" value="%2$s"/>', esc_attr($this->unique_prefix), esc_attr__('Export', $this->identifier)); 1159 $form .= sprintf('<input type="submit" class="button" name="%1$s_admin_reset" value="%2$s"/>', esc_attr($this->unique_prefix), esc_attr__('Reset', $this->identifier)); 1132 1160 $form .= '</p></fieldset></form></div>'; 1133 1161 return $form; … … 1140 1168 * @deprecated 7.0.0 1141 1169 */ 1142 function input_hidden($option)1170 public function input_hidden($option) 1143 1171 { 1144 1172 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_hidden'); … … 1155 1183 * @deprecated 7.0.0 1156 1184 */ 1157 function label($opt_id, $label)1185 public function label($opt_id, $label) 1158 1186 { 1159 1187 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::label'); 1160 printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);1188 printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), esc_html($label)); 1161 1189 } 1162 1190 /** … … 1171 1199 * @deprecated 7.0.0 1172 1200 */ 1173 function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '')1201 public function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '') 1174 1202 { 1175 1203 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_text'); … … 1187 1215 <td> 1188 1216 <?php printf('<input type="text" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s/><br />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false));?> 1189 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>1217 <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?> 1190 1218 </td> 1191 1219 </tr> … … 1206 1234 * @deprecated 7.0.0 1207 1235 */ 1208 function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')1236 public function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '') 1209 1237 { 1210 1238 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_number'); 1211 1239 $opt_id = adminKit::get_valid_id($option); 1212 1240 $opt_name = $this->unique_prefix . '_options[' . $option . ']'; 1213 $extras = '';1241 $extras_escaped = ''; 1214 1242 if($min !== '') 1215 1243 { 1216 $extras .= 'min="' . esc_attr($min) . '" ';1244 $extras_escaped .= 'min="' . esc_attr($min) . '" '; 1217 1245 } 1218 1246 if($max !== '') 1219 1247 { 1220 $extras .= 'max="' . esc_attr($max) . '" ';1248 $extras_escaped .= 'max="' . esc_attr($max) . '" '; 1221 1249 } 1222 1250 if($step !== '') 1223 1251 { 1224 $extras .= 'step="' . esc_attr($step) . '" ';1252 $extras_escaped .= 'step="' . esc_attr($step) . '" '; 1225 1253 } 1226 1254 if($disable) … … 1234 1262 </th> 1235 1263 <td> 1236 <?php printf('<input type="number" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %6$s%5$s/><br />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false), $extras );?>1237 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>1264 <?php printf('<input type="number" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %6$s%5$s/><br />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false), $extras_escaped);?> 1265 <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?> 1238 1266 </td> 1239 1267 </tr> … … 1251 1279 * @deprecated 7.0.0 1252 1280 */ 1253 function textbox($label, $option, $height = '3', $disable = false, $description = '', $class = '')1281 public function textbox($label, $option, $height = '3', $disable = false, $description = '', $class = '') 1254 1282 { 1255 1283 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::textbox'); … … 1268 1296 <td> 1269 1297 <?php printf('<textarea rows="%6$s" name="%1$s" id="%2$s" class="%4$s" %5$s/>%3$s</textarea><br />', esc_attr($opt_name), esc_attr($opt_id), esc_textarea($this->opt[$option]), esc_attr($class), disabled($disable, true, false), esc_attr($height));?> 1270 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>1298 <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?> 1271 1299 </td> 1272 1300 </tr> … … 1284 1312 * @deprecated 7.0.0 1285 1313 */ 1286 function tinymce($label, $option, $height = '3', $disable = false, $description = '')1314 public function tinymce($label, $option, $height = '3', $disable = false, $description = '') 1287 1315 { 1288 1316 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::tinymce'); … … 1300 1328 <td> 1301 1329 <?php printf('<textarea rows="%6$s" name="%1$s" id="%2$s" class="%4$s" %5$s/>%3$s</textarea><br />', esc_attr($opt_name), esc_attr($opt_id), esc_textarea($this->opt[$option]), esc_attr($class), disabled($disable, true, false), esc_attr($height));?> 1302 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>1330 <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?> 1303 1331 </td> 1304 1332 </tr> … … 1317 1345 * @deprecated 7.0.0 1318 1346 */ 1319 function input_check($label, $option, $instruction, $disable = false, $description = '', $class = '')1347 public function input_check($label, $option, $instruction, $disable = false, $description = '', $class = '') 1320 1348 { 1321 1349 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_check'); … … 1334 1362 <label for="<?php echo esc_attr( $opt_id ); ?>"> 1335 1363 <?php printf('<input type="checkbox" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s %6$s/>', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]), esc_attr($class), disabled($disable, true, false), checked($this->opt[$option], true, false));?> 1336 <?php echo $instruction; ?>1364 <?php echo esc_html($instruction); ?> 1337 1365 </label><br /> 1338 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>1366 <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?> 1339 1367 </td> 1340 1368 </tr> … … 1352 1380 * @deprecated 7.0.0 1353 1381 */ 1354 function input_radio($option, $value, $instruction, $disable = false, $class = '')1382 public function input_radio($option, $value, $instruction, $disable = false, $class = '') 1355 1383 { 1356 1384 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_radio'); … … 1365 1393 <label> 1366 1394 <?php printf('<input type="radio" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s %6$s/>', esc_attr($opt_name), esc_attr($opt_id), esc_attr($value), esc_attr($class), disabled($disable, true, false), checked($value, $this->opt[$option], false));?> 1367 <?php echo $instruction; ?>1395 <?php echo esc_html($instruction); ?> 1368 1396 </label><br/> 1369 1397 <?php … … 1382 1410 * @deprecated 7.0.0 1383 1411 */ 1384 function input_select($label, $option, $values, $disable = false, $description = '', $titles = false, $class = '')1412 public function input_select($label, $option, $values, $disable = false, $description = '', $titles = false, $class = '') 1385 1413 { 1386 1414 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_select'); … … 1403 1431 <td> 1404 1432 <?php printf('<select name="%1$s" id="%2$s" class="%4$s" %5$s>%3$s</select><br />', esc_attr($opt_name), esc_attr($opt_id), $this->select_options($option, $titles, $values), esc_attr($class), disabled($disable, true, false));?> 1405 <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>1433 <?php if($description !== ''){?><p class="description"><?php echo esc_html($description);?></p><?php }?> 1406 1434 </td> 1407 1435 </tr> … … 1420 1448 * @deprecated 7.0.0 1421 1449 */ 1422 function select_options($optionname, $options, $values, $exclude = array())1450 public function select_options($optionname, $options, $values, $exclude = array()) 1423 1451 { 1424 1452 _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::select_options'); … … 1430 1458 if(!in_array($option, $exclude)) 1431 1459 { 1432 $options_html .= sprintf('<option value="%1$s" %2$s>%3$s</option>', esc_attr($values[$key]), selected($value, $values[$key], false), $option);1460 $options_html .= sprintf('<option value="%1$s" %2$s>%3$s</option>', esc_attr($values[$key]), selected($value, $values[$key], false), esc_html($option)); 1433 1461 } 1434 1462 } … … 1441 1469 * @return mixed The value of the option 1442 1470 */ 1443 function get_option($option)1471 public function get_option($option) 1444 1472 { 1445 1473 return get_option($option); … … 1451 1479 * @param mixed $newvalue The new value to set the option to 1452 1480 */ 1453 function update_option($option, $newvalue, $autoload = null)1481 public function update_option($option, $newvalue, $autoload = null) 1454 1482 { 1455 1483 return update_option($option, $newvalue, $autoload); … … 1463 1491 * @param string $autoload Whether or not to autoload the option, it's a string because WP is special 1464 1492 */ 1465 function add_option($option, $value = '', $deprecated = '', $autoload = 'yes')1466 { 1467 return add_option($option, $value, null, $autoload);1493 public function add_option($option, $value = '', $deprecated = '', $autoload = 'yes') 1494 { 1495 return add_option($option, $value, '', $autoload); 1468 1496 } 1469 1497 /** … … 1472 1500 * @param string $option The name of the option to delete 1473 1501 */ 1474 function delete_option($option)1502 public function delete_option($option) 1475 1503 { 1476 1504 return delete_option($option); 1477 1505 } 1506 /** 1507 * Initializes localization textdomain for translations (if applicable) 1508 * 1509 * Will conditionally load the textdomain for translations. This is here for 1510 * plugins that span multiple files and have localization in more than one file 1511 * 1512 * @return void 1513 * 1514 * @deprecated 7.5.1 1515 */ 1516 public function local() 1517 { 1518 //Nothing to see here now that it's deprecated 1519 } 1478 1520 } -
breadcrumb-navxt/trunk/includes/adminKit/class-mtekk_adminkit_form.php
r3411622 r3425008 1 1 <?php 2 2 /* 3 Copyright 2015-202 3John Havlik (email : john.havlik@mtekk.us)3 Copyright 2015-2025 John Havlik (email : john.havlik@mtekk.us) 4 4 5 5 This program is free software; you can redistribute it and/or modify … … 76 76 public function label($opt_id, $label) 77 77 { 78 printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);78 printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), esc_html($label)); 79 79 } 80 80 /** … … 111 111 if($description !== '') 112 112 { 113 printf('<p class="description">%s</p>', $description);113 printf('<p class="description">%s</p>', esc_html($description)); 114 114 }?> 115 115 </td> … … 134 134 $opt_id = form::get_valid_id($option->get_name()); 135 135 $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']'; 136 $extras = '';136 $extras_escaped = ''; 137 137 if($min !== '') 138 138 { 139 $extras .= 'min="' . esc_attr($min) . '" ';139 $extras_escaped.= 'min="' . esc_attr($min) . '" '; 140 140 } 141 141 if($max !== '') 142 142 { 143 $extras .= 'max="' . esc_attr($max) . '" ';143 $extras_escaped.= 'max="' . esc_attr($max) . '" '; 144 144 } 145 145 if($step !== '') 146 146 { 147 $extras .= 'step="' . esc_attr($step) . '" ';147 $extras_escaped.= 'step="' . esc_attr($step) . '" '; 148 148 }?> 149 149 <tr valign="top"> … … 164 164 esc_attr($class), 165 165 disabled($disable, true, false), 166 $extras );167 if($description !== '') 168 { 169 printf('<p class="description">%s</p>', $description);166 $extras_escaped); 167 if($description !== '') 168 { 169 printf('<p class="description">%s</p>', esc_html($description)); 170 170 }?> 171 171 </td> … … 206 206 if($description !== '') 207 207 { 208 printf('<p class="description">%s</p>', $description);208 printf('<p class="description">%s</p>', esc_html($description)); 209 209 }?> 210 210 </td> … … 245 245 if($description !== '') 246 246 { 247 printf('<p class="description">%s</p>', $description);247 printf('<p class="description">%s</p>', esc_html($description)); 248 248 }?> 249 249 </td> … … 283 283 disabled($disable, true, false), 284 284 checked($option->get_value(), true, false)); 285 echo $instruction;?>285 echo esc_html($instruction);?> 286 286 </label><br /> 287 287 <?php 288 288 if($description !== '') 289 289 { 290 printf('<p class="description">%s</p>', $description);290 printf('<p class="description">%s</p>', esc_html($description)); 291 291 }?> 292 292 </td> … … 322 322 disabled($disable, true, false), 323 323 checked($value, $option->get_value(), false)); 324 echo $instruction; ?>324 echo esc_html($instruction); ?> 325 325 </label><br/> 326 326 <?php … … 364 364 if($description !== '') 365 365 { 366 printf('<p class="description">%s</p>', $description);366 printf('<p class="description">%s</p>', esc_html($description)); 367 367 }?> 368 368 </td> … … 391 391 esc_attr($values[$key]), 392 392 selected($current_value, $values[$key], false), 393 $option);393 esc_html($option)); 394 394 } 395 395 } -
breadcrumb-navxt/trunk/includes/adminKit/class-mtekk_adminkit_message.php
r2862997 r3425008 1 1 <?php 2 2 /* 3 Copyright 2015-202 3John Havlik (email : john.havlik@mtekk.us)3 Copyright 2015-2025 John Havlik (email : john.havlik@mtekk.us) 4 4 5 5 This program is free software; you can redistribute it and/or modify … … 42 42 { 43 43 //Let the user know they're doing it wrong 44 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, __('$uid must not be null if message is dismissible', 'mtekk_adminKit'), '1.0.0');44 _doing_it_wrong(__CLASS__ . '::' . __FUNCTION__, esc_html__('$uid must not be null if message is dismissible', 'mtekk_adminKit'), '1.0.0'); 45 45 //Treat the message as non-dismissible 46 46 $dismissible = false; … … 70 70 public function dismiss() 71 71 { 72 if($this->dismissible && isset($_POST['uid']) && esc_attr($_POST['uid']) === $this->uid)72 if($this->dismissible && isset($_POST['uid']) && sanitize_html_class($_POST['uid']) === $this->uid && check_ajax_referer($this->uid . '_dismiss', 'nonce')) 73 73 { 74 check_ajax_referer($this->uid . '_dismiss', 'nonce');75 74 $this->dismissed = true; 76 75 //If the message was dismissed, update the transient for 30 days … … 91 90 } 92 91 wp_enqueue_script('mtekk_adminkit_messages'); 93 printf('<div class="notice notice-%1$s is-dismissible"><p>%2$s</p><meta property="uid" content="%3$s"><meta property="nonce" content="%4$s"></div>', esc_attr($this->type), $this->contents, esc_attr($this->uid), wp_create_nonce($this->uid . '_dismiss'));92 printf('<div class="notice notice-%1$s is-dismissible"><p>%2$s</p><meta property="uid" content="%3$s"><meta property="nonce" content="%4$s"></div>', esc_attr($this->type), wp_kses_post($this->contents), esc_attr($this->uid), esc_attr(wp_create_nonce($this->uid . '_dismiss'))); 94 93 } 95 94 else 96 95 { 97 printf('<div class="notice notice-%1$s"><p>%2$s</p></div>', esc_attr($this->type), $this->contents);96 printf('<div class="notice notice-%1$s"><p>%2$s</p></div>', esc_attr($this->type), wp_kses_post($this->contents)); 98 97 } 99 98 } -
breadcrumb-navxt/trunk/includes/adminKit/setting/class-mtekk_adminkit_setting_string.php
r2862997 r3425008 48 48 return $this->value; 49 49 } 50 return esc_html($new_value);50 return sanitize_text_field($new_value); 51 51 } 52 52 /** -
breadcrumb-navxt/trunk/includes/blocks/build/breadcrumb-trail/block.json
r3411622 r3425008 75 75 }, 76 76 "usesContext": [ 77 " groupId"77 "postId" 78 78 ], 79 79 "selectors": { -
breadcrumb-navxt/trunk/includes/blocks/build/breadcrumb-trail/render.php
r3411622 r3425008 14 14 return; 15 15 } 16 //Handle previews17 if( isset($_REQUEST['post_id']))16 //Handle in-editor previews, function check to prevent requiring WP6.5 17 if(function_exists('wp_is_serving_rest_request') && wp_is_serving_rest_request() && current_user_can('read_post', absint($block->context['postId']))) 18 18 { 19 $post_id = $_REQUEST['post_id']; 20 $preview_post = get_post($post_id); 19 $preview_post = get_post(absint($block->context['postId'])); 21 20 if($attributes['format'] === 'list') 22 21 { … … 29 28 $outer_template = '%1$s'; 30 29 } 31 $trail_string = $GLOBALS['breadcrumb_navxt']->_display_post($preview_post, true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache'], $template, $outer_template);30 $trail_string_safe = $GLOBALS['breadcrumb_navxt']->_display_post($preview_post, true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache'], $template, $outer_template); 32 31 } 33 32 else if($attributes['format'] === 'list') 34 33 { 35 $trail_string = bcn_display_list(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']);34 $trail_string_safe = bcn_display_list(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']); 36 35 } 37 36 else 38 37 { 39 $trail_string = bcn_display(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']);38 $trail_string_safe = bcn_display(true, $attributes['link'], $attributes['reverseOrder'], $attributes['ignoreCache']); 40 39 } 41 40 if($attributes['format'] === 'list') … … 44 43 <span><?php echo wp_kses_post($attributes['pretext']);?></span> 45 44 <ol <?php echo wp_kses_data( get_block_wrapper_attributes( array('class' => 'breadcrumbs') ) );?>> 46 <?php echo $trail_string ; ?>45 <?php echo $trail_string_safe; ?> 47 46 </ol> 48 47 <?php … … 60 59 );?>> 61 60 <span><?php echo wp_kses_post($attributes['pretext']);?></span> 62 <?php echo $trail_string ;?>61 <?php echo $trail_string_safe;?> 63 62 </nav> 64 63 <?php … … 77 76 );?>> 78 77 <span><?php echo wp_kses_post($attributes['pretext']);?></span> 79 <?php echo $trail_string ;?>78 <?php echo $trail_string_safe;?> 80 79 </div> 81 80 <?php … … 91 90 );?>> 92 91 <span><?php echo wp_kses_post($attributes['pretext']);?></span> 93 <?php echo $trail_string ; ?>92 <?php echo $trail_string_safe; ?> 94 93 </div> 95 94 <?php … … 104 103 );?>> 105 104 <span><?php echo wp_kses_post($attributes['pretext']);?></span> 106 <?php echo $trail_string ; ?>105 <?php echo $trail_string_safe; ?> 107 106 </div> 108 107 <?php -
breadcrumb-navxt/trunk/options_upgrade.php
r3219937 r3425008 24 24 function bcn_phpold() 25 25 { 26 printf('<div class="notice notice-error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', phpversion(), '5.3.0'); 26 /* translators: %1$s: User's version of PHP, %2$s: Breadcrmb NavXT minimuum PHP version */ 27 printf('<div class="notice notice-error"><p>' . esc_html__('Your PHP version is too old, please upgrade to a newer version. Your version is %1$s, Breadcrumb NavXT requires %2$s', 'breadcrumb-navxt') . '</p></div>', esc_html(phpversion()), '7.0.0'); 27 28 } 28 29 //If we are in the admin, let's print a warning then return -
breadcrumb-navxt/trunk/readme.txt
r3411640 r3425008 5 5 Requires at least: 5.8 6 6 Tested up to: 6.9 7 Stable tag: 7.5. 07 Stable tag: 7.5.1 8 8 Requires PHP: 7.0 9 9 License: GPLv2 or later … … 50 50 51 51 == Changelog == 52 = 7.5.1 = 53 Release date: December, 21st 2025 54 55 * Behavior change: Removed deprecated `bcn_li_attributes` filter. 56 * Bug fix: Fixed issue where the block could be used to generate breadcrumb trails that were not for the current resource. 57 * Bug fix: Removed deprecated title length setting from settings page. 58 * Bug fix: Fixed issue where XML settings import did not properly validate imported settings. 59 52 60 = 7.5.0 = 53 61 Release date: December, 4th 2025
Note: See TracChangeset
for help on using the changeset viewer.