Breadcrumb NavXT - Version 7.0.0

Version Description

Release date: December, 17th 2021

  • Behavior change: Within the bcn_breadcrumb_trail object instead of passing term id and taxonomy, a WP_Term object is passed instead.
  • Behavior change: Attachments now use parent post type for post type argument.
  • New feature: Moved to adminKit 3.0
  • New feature: Core bcn_breadcrumb_trail object now supports multi dimensional trails.
  • New feature: Added bcn_opts_update_to_save filter.
  • Bug fix: Fixed parameter order issue in REST controller that resulted in PHP Deprecated message in PHP8.
  • Bug fix: Updated REST controller endpoint registration for better WordPress 5.5+ compatibility.
  • Bug fix: Fixed compatibility issue with Widget settings not saving properly in WordPress 5.8.
  • Bug fix: Fixed issue with the position count parameter within bcn_display when outputting a trail in reverse order.
Download this release

Release Info

Developer mtekk
Plugin Icon 128x128 Breadcrumb NavXT
Version 7.0.0
Comparing to
See all releases

Code changes from version 6.6.0 to 7.0.0

Files changed (31) hide show
  1. breadcrumb-navxt.php +268 -149
  2. class.bcn_admin.php +172 -341
  3. class.bcn_breadcrumb.php +34 -9
  4. class.bcn_breadcrumb_trail.php +152 -136
  5. class.bcn_network_admin.php +10 -9
  6. class.bcn_rest_controller.php +13 -11
  7. class.bcn_widget.php +13 -11
  8. includes/{mtekk_adminkit_engroups.js → adminKit/assets/mtekk_adminkit_engroups.js} +0 -0
  9. includes/{mtekk_adminkit_engroups.min.js → adminKit/assets/mtekk_adminkit_engroups.min.js} +0 -0
  10. includes/{mtekk_adminkit_messages.js → adminKit/assets/mtekk_adminkit_messages.js} +0 -0
  11. includes/{mtekk_adminkit_messages.min.js → adminKit/assets/mtekk_adminkit_messages.min.js} +0 -0
  12. includes/{mtekk_adminkit_tabs.css → adminKit/assets/mtekk_adminkit_tabs.css} +0 -0
  13. includes/{mtekk_adminkit_tabs.js → adminKit/assets/mtekk_adminkit_tabs.js} +0 -0
  14. includes/{mtekk_adminkit_tabs.min.css → adminKit/assets/mtekk_adminkit_tabs.min.css} +0 -0
  15. includes/{mtekk_adminkit_tabs.min.js → adminKit/assets/mtekk_adminkit_tabs.min.js} +0 -0
  16. includes/{class.mtekk_adminkit.php → adminKit/class-mtekk_adminkit.php} +269 -142
  17. includes/adminKit/class-mtekk_adminkit_form.php +394 -0
  18. includes/{class.mtekk_adminkit_message.php → adminKit/class-mtekk_adminkit_message.php} +3 -2
  19. includes/{class.mtekk_adminkit_uninstaller.php → adminKit/class-mtekk_adminkit_uninstaller.php} +2 -2
  20. includes/adminKit/setting/class-mtekk_adminkit_setting_absint.php +57 -0
  21. includes/adminKit/setting/class-mtekk_adminkit_setting_base.php +79 -0
  22. includes/adminKit/setting/class-mtekk_adminkit_setting_bool.php +66 -0
  23. includes/adminKit/setting/class-mtekk_adminkit_setting_enum.php +87 -0
  24. includes/adminKit/setting/class-mtekk_adminkit_setting_float.php +57 -0
  25. includes/adminKit/setting/class-mtekk_adminkit_setting_html.php +69 -0
  26. includes/adminKit/setting/class-mtekk_adminkit_setting_int.php +57 -0
  27. includes/adminKit/setting/class-mtekk_adminkit_setting_string.php +69 -0
  28. includes/adminKit/setting/interface-mtekk_adminkit_setting.php +49 -0
  29. options_upgrade.php +234 -0
  30. readme.txt +17 -3
  31. uninstall.php +2 -2
breadcrumb-navxt.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Breadcrumb NavXT
4
  Plugin URI: http://mtekk.us/code/breadcrumb-navxt/
5
  Description: Adds a breadcrumb navigation showing the visitor&#39;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: 6.6.0
7
  Author: John Havlik
8
  Author URI: http://mtekk.us/
9
  License: GPL2
@@ -11,7 +11,7 @@ Text Domain: breadcrumb-navxt
11
  Domain Path: /languages
12
  */
13
  /*
14
- Copyright 2007-2020 John Havlik (email : john.havlik@mtekk.us)
15
 
16
  This program is free software; you can redistribute it and/or modify
17
  it under the terms of the GNU General Public License as published by
@@ -44,9 +44,9 @@ if(version_compare(phpversion(), '5.3.0', '<'))
44
  }
45
  require_once(dirname(__FILE__) . '/includes/multibyte_supplicant.php');
46
  //Include admin base class
47
- if(!class_exists('mtekk_adminKit'))
48
  {
49
- require_once(dirname(__FILE__) . '/includes/class.mtekk_adminkit.php');
50
  }
51
  //Include the breadcrumb class
52
  require_once(dirname(__FILE__) . '/class.bcn_breadcrumb.php');
@@ -57,16 +57,19 @@ if(class_exists('WP_Widget'))
57
  //Include the WP 2.8+ widget class
58
  require_once(dirname(__FILE__) . '/class.bcn_widget.php');
59
  }
 
 
60
  $breadcrumb_navxt = null;
61
- //TODO change to extends mtekk_plugKit
62
  class breadcrumb_navxt
63
  {
64
- const version = '6.6.0';
65
  protected $name = 'Breadcrumb NavXT';
66
  protected $identifier = 'breadcrumb-navxt';
67
  protected $unique_prefix = 'bcn';
68
  protected $plugin_basename = null;
69
  protected $opt = null;
 
70
  protected $breadcrumb_trail = null;
71
  protected $admin = null;
72
  protected $rest_controller = null;
@@ -79,14 +82,12 @@ class breadcrumb_navxt
79
  {
80
  //We get our breadcrumb trail object from our constructor
81
  $this->breadcrumb_trail = $breadcrumb_trail;
82
- //Grab defaults from the breadcrumb_trail object
83
- $this->opt = $this->breadcrumb_trail->opt;
84
  //We set the plugin basename here
85
  $this->plugin_basename = plugin_basename(__FILE__);
86
  //We need to add in the defaults for CPTs and custom taxonomies after all other plugins are loaded
87
  add_action('wp_loaded', array($this, 'wp_loaded'), 15);
88
  add_action('rest_api_init', array($this, 'rest_api_init'), 10);
89
- //Run a little later than everyone else
90
  add_action('init', array($this, 'init'), 11);
91
  //Register the WordPress 2.8 Widget
92
  add_action('widgets_init', array($this, 'register_widget'));
@@ -95,24 +96,20 @@ class breadcrumb_navxt
95
  {
96
  require_once(dirname(__FILE__) . '/class.bcn_network_admin.php');
97
  //Instantiate our new admin object
98
- $this->admin = new bcn_network_admin($this->breadcrumb_trail, $this->plugin_basename);
99
  }
100
  //Load our main admin if in the dashboard, but only if we're not in the network dashboard (prevents goofy bugs)
101
  else if(is_admin() || defined('WP_UNINSTALL_PLUGIN'))
102
  {
103
  require_once(dirname(__FILE__) . '/class.bcn_admin.php');
104
  //Instantiate our new admin object
105
- $this->admin = new bcn_admin($this->breadcrumb_trail, $this->plugin_basename);
106
  }
107
  }
108
  public function init()
109
  {
110
- breadcrumb_navxt::setup_options($this->opt);
111
- if(!is_admin() || !isset($_POST[$this->unique_prefix . '_admin_reset']))
112
- {
113
- $this->get_settings(); //This breaks the reset options script, so only do it if we're not trying to reset the settings
114
- }
115
  add_filter('bcn_allowed_html', array($this, 'allowed_html'), 1, 1);
 
116
  //We want to run late for using our breadcrumbs
117
  add_filter('tha_breadcrumb_navigation', array($this, 'tha_compat'), 99);
118
  //Only include the REST API if enabled
@@ -121,6 +118,11 @@ class breadcrumb_navxt
121
  require_once(dirname(__FILE__) . '/class.bcn_rest_controller.php');
122
  $this->rest_controller = new bcn_rest_controller($this->breadcrumb_trail, $this->unique_prefix);
123
  }
 
 
 
 
 
124
  //Register Guternberg
125
  $this->register_block();
126
  }
@@ -167,12 +169,12 @@ class breadcrumb_navxt
167
  wp_set_script_translations($this->unique_prefix . '-breadcrumb-trail-block-script', 'breadcrumb-navxt');
168
  }
169
  //Setup some bcn settings
170
- //TODO: New settings arch should make this easier
171
  wp_add_inline_script($this->unique_prefix . '-breadcrumb-trail-block-script',
172
  $this->unique_prefix . 'Opts = ' . json_encode(
173
  array(
174
- 'bcurrent_item_linked' => $this->opt['bcurrent_item_linked'],
175
- 'hseparator' => $this->opt['hseparator']
176
  )) . ';',
177
  'before');
178
  }
@@ -309,7 +311,7 @@ class breadcrumb_navxt
309
  'itemprop' => true
310
  )
311
  );
312
- return mtekk_adminKit::array_merge_recursive($tags, $allowed_html);
313
  }
314
  public function get_version()
315
  {
@@ -317,140 +319,266 @@ class breadcrumb_navxt
317
  }
318
  public function wp_loaded()
319
  {
320
-
321
  }
322
  public function uninstall()
323
  {
324
  $this->admin->uninstall();
325
  }
326
- /**
327
- * Sets up the extended options for any CPTs, taxonomies or extensions
328
- *
329
- * @param array $opt The options array, passed by reference
330
- */
331
- static public function setup_options(&$opt)
332
- {
333
- //Add custom post types
334
- breadcrumb_navxt::find_posttypes($opt);
335
- //Add custom taxonomy types
336
- breadcrumb_navxt::find_taxonomies($opt);
337
- //Let others hook into our settings
338
- $opt = apply_filters('bcn_settings_init', $opt);
339
- }
340
- /**
341
- * Places settings into $opts array, if missing, for the registered post types
342
- *
343
- * @param array $opts
344
- */
345
- static function find_posttypes(&$opts)
346
  {
347
- global $wp_post_types, $wp_taxonomies;
348
- //Loop through all of the post types in the array
349
- foreach($wp_post_types as $post_type)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  {
351
- //We only want custom post types
352
- if(!$post_type->_builtin)
 
 
 
 
 
 
 
 
353
  {
354
- if(!isset($opts['bpost_' . $post_type->name . '_taxonomy_referer']))
355
- {
356
- //Default to not letting the refering page influence the referer
357
- $opts['bpost_' . $post_type->name . '_taxonomy_referer'] = false;
358
- }
359
- //If the post type does not have settings in the options array yet, we need to load some defaults
360
- if(!isset($opts['Hpost_' . $post_type->name . '_template']))
361
- {
362
- //Add the necessary option array members
363
- $opts['Hpost_' . $post_type->name . '_template'] = bcn_breadcrumb::get_default_template();
364
- }
365
- if(!isset($opts['Hpost_' . $post_type->name . '_template_no_anchor']))
366
- {
367
- $opts['Hpost_' . $post_type->name . '_template_no_anchor'] = bcn_breadcrumb::default_template_no_anchor;
368
- }
369
- if(!isset($opts['apost_' . $post_type->name . '_root']))
370
- {
371
- //Default to not showing a post_root
372
- $opts['apost_' . $post_type->name . '_root'] = 0;
373
- }
374
- if(!isset($opts['bpost_' . $post_type->name . '_hierarchy_display']))
375
- {
376
- //Default to not displaying a taxonomy
377
- $opts['bpost_' . $post_type->name . '_hierarchy_display'] = false;
378
- }
379
- if(!isset($opts['Spost_' . $post_type->name . '_hierarchy_type']))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  {
381
- if($post_type->has_archive == true || is_string($post_type->has_archive))
 
382
  {
383
- $opts['bpost_' . $post_type->name . '_archive_display'] = true;
384
  }
385
- else
 
386
  {
387
- $opts['bpost_' . $post_type->name . '_archive_display'] = false;
388
- }
389
- if(!$post_type->hierarchical)
390
- {
391
- //Loop through all of the possible taxonomies
392
- foreach($wp_taxonomies as $taxonomy)
393
  {
394
- //Check for non-public taxonomies
395
- if(!apply_filters('bcn_show_tax_private', $taxonomy->public, $taxonomy->name, $post_type->name))
396
- {
397
- continue;
398
- }
399
- //Activate the first taxonomy valid for this post type and exit the loop
400
- if($taxonomy->object_type == $post_type->name || in_array($post_type->name, $taxonomy->object_type))
401
- {
402
- $opts['bpost_' . $post_type->name . '_hierarchy_display'] = true;
403
- $opts['Spost_' . $post_type->name . '_hierarchy_type'] = $taxonomy->name;
404
- break;
405
- }
406
  }
407
  }
408
- else
409
- {
410
- $opts['bpost_' . $post_type->name . '_hierarchy_display'] = true;
411
- $opts['Spost_' . $post_type->name . '_hierarchy_type'] = 'BCN_PARENT';
412
- }
413
- //If there are no valid taxonomies for this type, setup our defaults
414
- if(!isset($opts['Spost_' . $post_type->name . '_hierarchy_type']))
415
- {
416
- $opts['Spost_' . $post_type->name . '_hierarchy_type'] = 'BCN_DATE';
417
- }
418
- //Run through some filters, allowing extensions to directly influence the default hierarchy selection/display
419
- $opts['Spost_' . $post_type->name . '_hierarchy_type'] = apply_filters('bcn_default_hierarchy_type', $opts['Spost_' . $post_type->name . '_hierarchy_type'], $post_type->name);
420
- $opts['bpost_' . $post_type->name . '_hierarchy_display'] = apply_filters('bcn_default_hierarchy_display', $opts['bpost_' . $post_type->name . '_hierarchy_display'], $post_type->name, $opts['Spost_' . $post_type->name . '_hierarchy_type']);
421
  }
422
- //New for 6.2
423
- if(!isset($opts['bpost_' . $post_type->name . '_hierarchy_parent_first']))
424
  {
425
- $opts['bpost_' . $post_type->name . '_hierarchy_parent_first'] = false;
426
- $opts['bpost_' . $post_type->name . '_hierarchy_parent_first'] = apply_filters('bcn_default_hierarchy_parent_first', $opts['bpost_' . $post_type->name . '_hierarchy_parent_first'], $post_type->name);
427
  }
428
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
429
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  }
431
  /**
432
- * Places settings into $opts array, if missing, for the registered taxonomies
433
  *
434
- * @param $opts
 
435
  */
436
- static function find_taxonomies(&$opts)
437
  {
438
- global $wp_taxonomies;
439
- //We'll add our custom taxonomy stuff at this time
440
- foreach($wp_taxonomies as $taxonomy)
441
- {
442
- //We only want custom taxonomies
443
- if(!$taxonomy->_builtin)
444
- {
445
- //If the taxonomy does not have settings in the options array yet, we need to load some defaults
446
- if(!isset($opts['Htax_' . $taxonomy->name . '_template']))
447
- {
448
- //Add the necessary option array members
449
- $opts['Htax_' . $taxonomy->name . '_template'] = __(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');
450
- $opts['Htax_' . $taxonomy->name . '_template_no_anchor'] = __(sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%%htitle%%</span><meta property="position" content="%%position%%"></span>', $taxonomy->labels->singular_name), 'breadcrumb-navxt');
451
- }
452
- }
453
- }
454
  }
455
  /**
456
  * Hooks into the theme hook alliance tha_breadcrumb_navigation filter and replaces the trail
@@ -471,15 +599,20 @@ class breadcrumb_navxt
471
  */
472
  private function get_settings()
473
  {
 
 
 
 
 
474
  //Grab the current settings for the current local site from the db
475
- $this->breadcrumb_trail->opt = wp_parse_args(get_option('bcn_options'), $this->opt);
476
  //If we're in multisite mode, look at the three BCN_SETTINGS globals
477
  if(is_multisite())
478
  {
479
  if(defined('BCN_SETTINGS_USE_NETWORK') && BCN_SETTINGS_USE_NETWORK)
480
  {
481
  //Grab the current network wide settings
482
- $this->breadcrumb_trail->opt = wp_parse_args(get_site_option('bcn_options'), $this->opt);
483
  }
484
  else if(defined('BCN_SETTINGS_FAVOR_LOCAL') && BCN_SETTINGS_FAVOR_LOCAL)
485
  {
@@ -495,25 +628,10 @@ class breadcrumb_navxt
495
  //Currently only support using post_parent for the page hierarchy
496
  $this->breadcrumb_trail->opt['bpost_page_hierarchy_display'] = true;
497
  $this->breadcrumb_trail->opt['bpost_page_hierarchy_parent_first'] = true;
498
- $this->breadcrumb_trail->opt['Spost_page_hierarchy_type'] = 'BCN_POST_PARENT';
499
  $this->breadcrumb_trail->opt['apost_page_root'] = get_option('page_on_front');
500
  //This one isn't needed as it is performed in bcn_breadcrumb_trail::fill(), it's here for completeness only
501
  $this->breadcrumb_trail->opt['apost_post_root'] = get_option('page_for_posts');
502
-
503
- //Loop through all of the post types in the array, migrate automatically if necessary
504
- foreach($GLOBALS['wp_post_types'] as $post_type)
505
- {
506
- if(isset($this->opt['Spost_' . $post_type->name . '_taxonomy_type']))
507
- {
508
- $this->opt['Spost_' . $post_type->name . '_hierarchy_type'] = $this->opt['Spost_' . $post_type->name . '_taxonomy_type'];
509
- unset($this->opt['Spost_' . $post_type->name . '_taxonomy_type']);
510
- }
511
- if(isset($this->opt['Spost_' . $post_type->name . '_taxonomy_display']))
512
- {
513
- $this->opt['Spost_' . $post_type->name . '_hierarchy_display'] = $this->opt['Spost_' . $post_type->name . '_taxonomy_display'];
514
- unset($this->opt['Spost_' . $post_type->name . '_taxonomy_display']);
515
- }
516
- }
517
  }
518
  /**
519
  * Outputs the breadcrumb trail
@@ -523,11 +641,12 @@ class breadcrumb_navxt
523
  * @param bool $reverse Whether to reverse the output or not.
524
  * @param bool $force Whether or not to force the fill function to run.
525
  * @param string $template The template to use for the string output.
 
526
  *
527
  * @return void Void if Option to print out breadcrumb trail was chosen.
528
  * @return string String-Data of breadcrumb trail.
529
  */
530
- public function display($return = false, $linked = true, $reverse = false, $force = false, $template = '%1$s%2$s')
531
  {
532
  //If we're being forced to fill the trail, clear it before calling fill
533
  if($force)
@@ -641,7 +760,7 @@ function bcn_display_list($return = false, $linked = true, $reverse = false, $fo
641
  global $breadcrumb_navxt;
642
  if($breadcrumb_navxt !== null)
643
  {
644
- return $breadcrumb_navxt->display($return, $linked, $reverse, $force, "<li%3\$s>%1\$s</li>\n");
645
  }
646
  }
647
  /**
3
  Plugin Name: Breadcrumb NavXT
4
  Plugin URI: http://mtekk.us/code/breadcrumb-navxt/
5
  Description: Adds a breadcrumb navigation showing the visitor&#39;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.0.0
7
  Author: John Havlik
8
  Author URI: http://mtekk.us/
9
  License: GPL2
11
  Domain Path: /languages
12
  */
13
  /*
14
+ Copyright 2007-2021 John Havlik (email : john.havlik@mtekk.us)
15
 
16
  This program is free software; you can redistribute it and/or modify
17
  it under the terms of the GNU General Public License as published by
44
  }
45
  require_once(dirname(__FILE__) . '/includes/multibyte_supplicant.php');
46
  //Include admin base class
47
+ if(!class_exists('\mtekk\adminKit\adminKit'))
48
  {
49
+ require_once(dirname(__FILE__) . '/includes/adminKit/class-mtekk_adminkit.php');
50
  }
51
  //Include the breadcrumb class
52
  require_once(dirname(__FILE__) . '/class.bcn_breadcrumb.php');
57
  //Include the WP 2.8+ widget class
58
  require_once(dirname(__FILE__) . '/class.bcn_widget.php');
59
  }
60
+ use mtekk\adminKit\adminKit as adminKit;
61
+ use mtekk\adminKit\setting;
62
  $breadcrumb_navxt = null;
63
+ //TODO change to extends \mtekk\plugKit
64
  class breadcrumb_navxt
65
  {
66
+ const version = '7.0.0';
67
  protected $name = 'Breadcrumb NavXT';
68
  protected $identifier = 'breadcrumb-navxt';
69
  protected $unique_prefix = 'bcn';
70
  protected $plugin_basename = null;
71
  protected $opt = null;
72
+ protected $settings = array();
73
  protected $breadcrumb_trail = null;
74
  protected $admin = null;
75
  protected $rest_controller = null;
82
  {
83
  //We get our breadcrumb trail object from our constructor
84
  $this->breadcrumb_trail = $breadcrumb_trail;
 
 
85
  //We set the plugin basename here
86
  $this->plugin_basename = plugin_basename(__FILE__);
87
  //We need to add in the defaults for CPTs and custom taxonomies after all other plugins are loaded
88
  add_action('wp_loaded', array($this, 'wp_loaded'), 15);
89
  add_action('rest_api_init', array($this, 'rest_api_init'), 10);
90
+ //Run a little later than everyone else to give other plugins a chance to hook into the filters and actions in this
91
  add_action('init', array($this, 'init'), 11);
92
  //Register the WordPress 2.8 Widget
93
  add_action('widgets_init', array($this, 'register_widget'));
96
  {
97
  require_once(dirname(__FILE__) . '/class.bcn_network_admin.php');
98
  //Instantiate our new admin object
99
+ $this->admin = new bcn_network_admin($this->breadcrumb_trail->opt, $this->plugin_basename, $this->settings);
100
  }
101
  //Load our main admin if in the dashboard, but only if we're not in the network dashboard (prevents goofy bugs)
102
  else if(is_admin() || defined('WP_UNINSTALL_PLUGIN'))
103
  {
104
  require_once(dirname(__FILE__) . '/class.bcn_admin.php');
105
  //Instantiate our new admin object
106
+ $this->admin = new bcn_admin($this->breadcrumb_trail->opt, $this->plugin_basename, $this->settings);
107
  }
108
  }
109
  public function init()
110
  {
 
 
 
 
 
111
  add_filter('bcn_allowed_html', array($this, 'allowed_html'), 1, 1);
112
+ add_filter('mtekk_adminkit_allowed_html', array($this, 'allowed_html'), 1, 1);
113
  //We want to run late for using our breadcrumbs
114
  add_filter('tha_breadcrumb_navigation', array($this, 'tha_compat'), 99);
115
  //Only include the REST API if enabled
118
  require_once(dirname(__FILE__) . '/class.bcn_rest_controller.php');
119
  $this->rest_controller = new bcn_rest_controller($this->breadcrumb_trail, $this->unique_prefix);
120
  }
121
+ $this->setup_setting_defaults();
122
+ if(!is_admin() || (!isset($_POST[$this->unique_prefix . '_admin_reset']) && !isset($_POST[$this->unique_prefix . '_admin_options'])))
123
+ {
124
+ $this->get_settings(); //This breaks the reset options script, so only do it if we're not trying to reset the settings
125
+ }
126
  //Register Guternberg
127
  $this->register_block();
128
  }
169
  wp_set_script_translations($this->unique_prefix . '-breadcrumb-trail-block-script', 'breadcrumb-navxt');
170
  }
171
  //Setup some bcn settings
172
+ //TODO: 3rd gen settings arch should make this easier
173
  wp_add_inline_script($this->unique_prefix . '-breadcrumb-trail-block-script',
174
  $this->unique_prefix . 'Opts = ' . json_encode(
175
  array(
176
+ 'bcurrent_item_linked' => $this->settings['bcurrent_item_linked']->get_value(),
177
+ 'hseparator' => $this->settings['hseparator']->get_value()
178
  )) . ';',
179
  'before');
180
  }
311
  'itemprop' => true
312
  )
313
  );
314
+ return adminKit::array_merge_recursive($tags, $allowed_html);
315
  }
316
  public function get_version()
317
  {
319
  }
320
  public function wp_loaded()
321
  {
322
+
323
  }
324
  public function uninstall()
325
  {
326
  $this->admin->uninstall();
327
  }
328
+ public function setup_setting_defaults()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
329
  {
330
+ $this->settings['bmainsite_display'] = new setting\setting_bool(
331
+ 'mainsite_display',
332
+ true,
333
+ __('Main Site Breadcrumb', 'breadcrumb-navxt'));
334
+ $this->settings['Hmainsite_template'] = new setting\setting_html(
335
+ 'mainsite_template',
336
+ bcn_breadcrumb::get_default_template(),
337
+ __('Main Site Home Template', 'breadcrumb-navxt'));
338
+ $this->settings['Hmainsite_template_no_anchor'] = new setting\setting_html(
339
+ 'mainsite_template_no_anchor',
340
+ bcn_breadcrumb::default_template_no_anchor,
341
+ __('Main Site Home Template (Unlinked)', 'breadcrumb-navxt'));
342
+ $this->settings['bhome_display'] = new setting\setting_bool(
343
+ 'home_display',
344
+ true,
345
+ __('Home Breadcrumb', 'breadcrumb-navxt'));
346
+ $this->settings['Hhome_template'] = new setting\setting_html(
347
+ 'home_template',
348
+ bcn_breadcrumb::get_default_template(),
349
+ __('Home Template', 'breadcrumb-navxt'));
350
+ $this->settings['Hhome_template_no_anchor'] = new setting\setting_html(
351
+ 'home_template_no_anchor',
352
+ bcn_breadcrumb::default_template_no_anchor,
353
+ __('Home Template (Unlinked)', 'breadcrumb-navxt'));
354
+ $this->settings['bblog_display'] = new setting\setting_bool(
355
+ 'blog_display',
356
+ true,
357
+ __('Blog Breadcrumb', 'breadcrumb-navxt'));
358
+ $this->settings['hseparator'] = new setting\setting_html(
359
+ 'separator',
360
+ ' &gt; ',
361
+ __('Breadcrumb Separator', 'breadcrumb-navxt'),
362
+ true);
363
+ $this->settings['hseparator_higher_dim'] = new setting\setting_html(
364
+ 'separator_higher_dim',
365
+ ', ',
366
+ __('Breadcrumb Separator (Higher Dimension)', 'breadcrumb-navxt'),
367
+ true);
368
+ $this->settings['bcurrent_item_linked'] = new setting\setting_bool(
369
+ 'current_item_linked',
370
+ false,
371
+ __('Link Current Item', 'breadcrumb-navxt'));
372
+ $this->settings['Hpaged_template'] = new setting\setting_html(
373
+ 'paged_template',
374
+ sprintf('<span class="%%type%%">%1$s</span>', esc_attr__('Page %htitle%', 'breadcrumb-navxt')),
375
+ _x('Paged Template', 'Paged as in when on an archive or post that is split into multiple pages', 'breadcrumb-navxt'));
376
+ $this->settings['bpaged_display'] = new setting\setting_bool(
377
+ 'paged_display',
378
+ false,
379
+ _x('Paged Breadcrumb', 'Paged as in when on an archive or post that is split into multiple pages', 'breadcrumb-navxt'));
380
+ //Post types
381
+ foreach($GLOBALS['wp_post_types']as $post_type)
382
  {
383
+ $this->settings['Hpost_' . $post_type->name . '_template'] = new setting\setting_html(
384
+ 'post_' . $post_type->name . '_template',
385
+ bcn_breadcrumb::get_default_template(),
386
+ sprintf(__('%s Template', 'breadcrumb-navxt'), $post_type->labels->singular_name));
387
+ $this->settings['Hpost_' . $post_type->name . '_template_no_anchor'] = new setting\setting_html(
388
+ 'post_' . $post_type->name . '_template_no_anchor',
389
+ bcn_breadcrumb::default_template_no_anchor,
390
+ sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $post_type->labels->singular_name));
391
+ //Root default depends on post type
392
+ if($post_type->name === 'page')
393
  {
394
+ $default_root = get_option('page_on_front');
395
+ }
396
+ else if($post_type->name === 'post')
397
+ {
398
+ $default_root = get_option('page_for_posts');
399
+ }
400
+ else
401
+ {
402
+ $default_root = 0;
403
+ }
404
+ $this->settings['apost_' . $post_type->name . '_root'] = new setting\setting_absint(
405
+ 'post_' . $post_type->name . '_root',
406
+ $default_root,
407
+ sprintf(__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name));
408
+ //Archive display default depends on post type
409
+ if($post_type->has_archive == true || is_string($post_type->has_archive))
410
+ {
411
+ $default_archive_display = true;
412
+ }
413
+ else
414
+ {
415
+ $default_archive_display = false;
416
+ }
417
+ $this->settings['bpost_' . $post_type->name . '_archive_display'] = new setting\setting_bool(
418
+ 'post_' . $post_type->name . '_archive_display',
419
+ $default_archive_display,
420
+ sprintf(__('%s Archive Display', 'breadcrumb-navxt'), $post_type->labels->singular_name));
421
+ $this->settings['bpost_' . $post_type->name . '_taxonomy_referer'] = new setting\setting_bool(
422
+ 'post_' . $post_type->name . '_taxonomy_referer',
423
+ false,
424
+ sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name));
425
+ //Hierarchy use parent first depends on post type
426
+ if(in_array($post_type->name, array('page', 'post')))
427
+ {
428
+ $default_parent_first = false;
429
+ }
430
+ else if($post_type->name === 'attachment')
431
+ {
432
+ $default_parent_first = true;
433
+ }
434
+ else
435
+ {
436
+ $default_parent_first = apply_filters('bcn_default_hierarchy_parent_first', false, $post_type->name);
437
+ }
438
+ $this->settings['bpost_' . $post_type->name . '_hierarchy_parent_first'] = new setting\setting_bool(
439
+ 'post_' . $post_type->name . '_hierarchy_parent_first',
440
+ $default_parent_first,
441
+ sprintf(__('%s Hierarchy Use Parent First', 'breadcrumb-navxt'), $post_type->labels->singular_name));
442
+ //Hierarchy depends on post type
443
+ if($post_type->name === 'page')
444
+ {
445
+ $hierarchy_type_allowed_values = array('BCN_POST_PARENT');
446
+ $hierarchy_type_default = 'BCN_POST_PARENT';
447
+ $default_hierarchy_display = true;
448
+ }
449
+ else
450
+ {
451
+ $hierarchy_type_allowed_values = array('BCN_POST_PARENT', 'BCN_DATE');
452
+ $hierarchy_type_default = 'BCN_POST_PARENT';
453
+ $default_hierarchy_display = false;
454
+ //Loop through all of the possible taxonomies
455
+ foreach($GLOBALS['wp_taxonomies'] as $taxonomy)
456
  {
457
+ //Check for non-public taxonomies
458
+ if(!apply_filters('bcn_show_tax_private', $taxonomy->public, $taxonomy->name, $post_type->name))
459
  {
460
+ continue;
461
  }
462
+ //Add valid taxonomies to list
463
+ if($taxonomy->object_type == $post_type->name || in_array($post_type->name, $taxonomy->object_type))
464
  {
465
+ $hierarchy_type_allowed_values[] = $taxonomy->name;
466
+ $default_hierarchy_display = true;
467
+ //Only change from default on first valid taxonomy, if not a hierarchcial post type
468
+ if($hierarchy_type_default === 'BCN_POST_PARENT')
 
 
469
  {
470
+ $hierarchy_type_default = $taxonomy->name;
 
 
 
 
 
 
 
 
 
 
 
471
  }
472
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
473
  }
474
+ //For hierarchical post types and attachments, override whatever we may have done in the taxonomy finding
475
+ if($post_type->hierarchical === true || $post_type->name === 'attachment')
476
  {
477
+ $default_hierarchy_display = true;
478
+ $hierarchy_type_default = 'BCN_POST_PARENT';
479
  }
480
  }
481
+ $this->settings['bpost_' . $post_type->name . '_hierarchy_display'] = new setting\setting_bool(
482
+ 'post_' . $post_type->name . '_hierarchy_display',
483
+ $default_hierarchy_display,
484
+ sprintf(__('%s Hierarchy Display', 'breadcrumb-navxt'), $post_type->labels->singular_name));
485
+ $this->settings['Epost_' . $post_type->name . '_hierarchy_type'] = new setting\setting_enum(
486
+ 'post_' . $post_type->name . '_hierarchy_type',
487
+ $hierarchy_type_default,
488
+ sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name),
489
+ false,
490
+ false,
491
+ $hierarchy_type_allowed_values);
492
+ }
493
+ //Taxonomies
494
+ foreach($GLOBALS['wp_taxonomies']as $taxonomy)
495
+ {
496
+ $this->settings['Htax_' . $taxonomy->name. '_template'] = new setting\setting_html(
497
+ 'tax_' . $taxonomy->name. '_template',
498
+ __(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'),
499
+ sprintf(__('%s Template', 'breadcrumb-navxt'), $taxonomy->labels->singular_name));
500
+ $this->settings['Htax_' . $taxonomy->name. '_template_no_anchor'] = new setting\setting_html(
501
+ 'tax_' . $taxonomy->name. '_template_no_anchor',
502
+ bcn_breadcrumb::default_template_no_anchor,
503
+ sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $taxonomy->labels->singular_name));
504
  }
505
+ //Miscellaneous
506
+ $this->settings['H404_template'] = new setting\setting_html(
507
+ '404_template',
508
+ bcn_breadcrumb::get_default_template(),
509
+ __('404 Template', 'breadcrumb-navxt'));
510
+ $this->settings['S404_title'] = new setting\setting_string(
511
+ '404_title',
512
+ __('404', 'breadcrumb-navxt'),
513
+ __('404 Title', 'breadcrumb-navxt'));
514
+ $this->settings['Hsearch_template'] = new setting\setting_html(
515
+ 'search_template',
516
+ sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>',
517
+ sprintf(esc_attr__('Search results for &#39;%1$s&#39;', 'breadcrumb-navxt'),
518
+ 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')))),
519
+ __('Search Template', 'breadcrumb-navxt'));
520
+ $this->settings['Hsearch_template_no_anchor'] = new setting\setting_html(
521
+ 'search_template_no_anchor',
522
+ sprintf('<span class="%%type%%">%1$s</span>',
523
+ sprintf(esc_attr__('Search results for &#39;%1$s&#39;', 'breadcrumb-navxt'), '%htitle%')),
524
+ __('Search Template (Unlinked)', 'breadcrumb-navxt'));
525
+ $this->settings['Hdate_template'] = new setting\setting_html(
526
+ 'date_template',
527
+ sprintf('<span property="itemListElement" typeof="ListItem"><a property="item" typeof="WebPage" title="%1$s" href="%%link%%" class="%%type%%" bcn-aria-current><span property="name">%%htitle%%</span></a><meta property="position" content="%%position%%"></span>', esc_attr__('Go to the %title% archives.', 'breadcrumb-navxt')),
528
+ __('Date Template', 'breadcrumb-navxt'));
529
+ $this->settings['Hdate_template_no_anchor'] = new setting\setting_html(
530
+ 'date_template_no_anchor',
531
+ bcn_breadcrumb::default_template_no_anchor,
532
+ __('Date Template (Unlinked)', 'breadcrumb-navxt'));
533
+ $this->settings['Hauthor_template'] = new setting\setting_html(
534
+ 'author_template',
535
+ sprintf('<span property="itemListElement" typeof="ListItem"><span property="name">%1$s</span><meta property="position" content="%%position%%"></span>',
536
+ sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'),
537
+ 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')))),
538
+ __('Author Template', 'breadcrumb-navxt'));
539
+ $this->settings['Hauthor_template_no_anchor'] = new setting\setting_html(
540
+ 'author_template_no_anchor',
541
+ sprintf('<span class="%%type%%">%1$s</span>',
542
+ sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')),
543
+ __('Author Template (Unlinked)', 'breadcrumb-navxt'));
544
+ $this->settings['aauthor_root'] = new setting\setting_absint(
545
+ 'author_root',
546
+ 0,
547
+ __('Author Root Page', 'breadcrumb-navxt'));
548
+ $this->settings['Eauthor_name'] = new setting\setting_enum(
549
+ 'author_name',
550
+ 'display_name',
551
+ __('Author Display Format', 'breadcrumb-navxt'),
552
+ false,
553
+ false,
554
+ array('display_name', 'nickname', 'first_name', 'last_name'));
555
+ /**
556
+ * Here are some deprecated settings
557
+ */
558
+ $this->settings['blimit_title'] = new setting\setting_bool(
559
+ 'limit_title',
560
+ false,
561
+ __('Limit Title Length', 'breadcrumb-navxt'),
562
+ false,
563
+ true);
564
+ $this->settings['amax_title_length'] = new setting\setting_absint(
565
+ 'max_title_length',
566
+ 30,
567
+ __('Maximum Title Length', 'breadcrumb-navxt'),
568
+ false,
569
+ true);
570
+ //Hook for letting others modify our default settings
571
+ $this->settings = apply_filters('bcn_settings_init', $this->settings);
572
  }
573
  /**
574
+ * Sets up the extended options for any CPTs, taxonomies or extensions
575
  *
576
+ * @param array $opt The options array, passed by reference
577
+ * @deprecated 7.0
578
  */
579
+ static public function setup_options(&$opt)
580
  {
581
+ //Do nothing by default, deprecated and keeping just for compatibility
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
582
  }
583
  /**
584
  * Hooks into the theme hook alliance tha_breadcrumb_navigation filter and replaces the trail
599
  */
600
  private function get_settings()
601
  {
602
+ //Convert our settings to opts
603
+ $opts = adminKit::settings_to_opts($this->settings);
604
+ //Run setup_options for compatibilty reasons
605
+ breadcrumb_navxt::setup_options($opts);
606
+
607
  //Grab the current settings for the current local site from the db
608
+ $this->breadcrumb_trail->opt = wp_parse_args(get_option('bcn_options'), $opts);
609
  //If we're in multisite mode, look at the three BCN_SETTINGS globals
610
  if(is_multisite())
611
  {
612
  if(defined('BCN_SETTINGS_USE_NETWORK') && BCN_SETTINGS_USE_NETWORK)
613
  {
614
  //Grab the current network wide settings
615
+ $this->breadcrumb_trail->opt = wp_parse_args(get_site_option('bcn_options'), $opts);
616
  }
617
  else if(defined('BCN_SETTINGS_FAVOR_LOCAL') && BCN_SETTINGS_FAVOR_LOCAL)
618
  {
628
  //Currently only support using post_parent for the page hierarchy
629
  $this->breadcrumb_trail->opt['bpost_page_hierarchy_display'] = true;
630
  $this->breadcrumb_trail->opt['bpost_page_hierarchy_parent_first'] = true;
631
+ $this->breadcrumb_trail->opt['Epost_page_hierarchy_type'] = 'BCN_POST_PARENT';
632
  $this->breadcrumb_trail->opt['apost_page_root'] = get_option('page_on_front');
633
  //This one isn't needed as it is performed in bcn_breadcrumb_trail::fill(), it's here for completeness only
634
  $this->breadcrumb_trail->opt['apost_post_root'] = get_option('page_for_posts');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
635
  }
636
  /**
637
  * Outputs the breadcrumb trail
641
  * @param bool $reverse Whether to reverse the output or not.
642
  * @param bool $force Whether or not to force the fill function to run.
643
  * @param string $template The template to use for the string output.
644
+ * @param string $outer_template The template to place an entire dimension of the trail into for all dimensions higher than 1.
645
  *
646
  * @return void Void if Option to print out breadcrumb trail was chosen.
647
  * @return string String-Data of breadcrumb trail.
648
  */
649
+ public function display($return = false, $linked = true, $reverse = false, $force = false, $template = '%1$s%2$s', $outer_template = '%1$s')
650
  {
651
  //If we're being forced to fill the trail, clear it before calling fill
652
  if($force)
760
  global $breadcrumb_navxt;
761
  if($breadcrumb_navxt !== null)
762
  {
763
+ return $breadcrumb_navxt->display($return, $linked, $reverse, $force, "<li%3\$s>%1\$s</li>\n", "<ul>%1\$s</ul>\n");
764
  }
765
  }
766
  /**
class.bcn_admin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2015-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -33,17 +33,18 @@ if(version_compare(phpversion(), '5.3.0', '<'))
33
  return;
34
  }
35
  //Include admin base class
36
- if(!class_exists('mtekk_adminKit'))
37
  {
38
- require_once(dirname(__FILE__) . '/includes/class.mtekk_adminkit.php');
39
  }
 
40
  /**
41
  * The administrative interface class
42
  *
43
  */
44
- class bcn_admin extends mtekk_adminKit
45
  {
46
- const version = '6.6.0';
47
  protected $full_name = 'Breadcrumb NavXT Settings';
48
  protected $short_name = 'Breadcrumb NavXT';
49
  protected $access_level = 'bcn_manage_options';
@@ -51,23 +52,61 @@ class bcn_admin extends mtekk_adminKit
51
  protected $unique_prefix = 'bcn';
52
  protected $plugin_basename = null;
53
  protected $support_url = 'https://wordpress.org/support/plugin/breadcrumb-navxt/';
54
- protected $breadcrumb_trail = null;
55
  /**
56
  * Administrative interface class default constructor
57
  *
58
- * @param bcn_breadcrumb_trail $breadcrumb_trail a breadcrumb trail object
59
  * @param string $basename The basename of the plugin
 
60
  */
61
- function __construct(bcn_breadcrumb_trail &$breadcrumb_trail, $basename)
62
  {
63
- $this->breadcrumb_trail =& $breadcrumb_trail;
64
  $this->plugin_basename = $basename;
65
  $this->full_name = esc_html__('Breadcrumb NavXT Settings', 'breadcrumb-navxt');
66
- //Grab defaults from the breadcrumb_trail object
67
- $this->opt =& $this->breadcrumb_trail->opt;
68
  //We're going to make sure we load the parent's constructor
69
  parent::__construct();
70
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  /**
72
  * admin initialization callback function
73
  *
@@ -80,22 +119,7 @@ class bcn_admin extends mtekk_adminKit
80
  {
81
  //We're going to make sure we run the parent's version of this function as well
82
  parent::init();
83
- }
84
- function wp_loaded()
85
- {
86
- parent::wp_loaded();
87
- breadcrumb_navxt::setup_options($this->opt);
88
- }
89
- /**
90
- * Sets hard constants into the options array
91
- *
92
- * @param &$opts The options array to set hard constants into
93
- */
94
- function opts_fix(&$opts)
95
- {
96
- $opts['bpost_page_hierarchy_display'] = true;
97
- $opts['Spost_page_hierarchy_type'] = 'BCN_POST_PARENT';
98
- $opts['apost_page_root'] = get_option('page_on_front');
99
  }
100
  /**
101
  * Upgrades input options array, sets to $this->opt
@@ -105,205 +129,15 @@ class bcn_admin extends mtekk_adminKit
105
  */
106
  function opts_upgrade($opts, $version)
107
  {
108
- global $wp_post_types, $wp_taxonomies;
109
  //If our version is not the same as in the db, time to update
110
  if(version_compare($version, $this::version, '<'))
111
  {
112
- //Upgrading to 3.8.1
113
- if(version_compare($version, '3.8.1', '<'))
114
- {
115
- $opts['post_page_root'] = $this->get_option('page_on_front');
116
- $opts['post_post_root'] = $this->get_option('page_for_posts');
117
- }
118
- //Upgrading to 4.0
119
- if(version_compare($version, '4.0.0', '<'))
120
- {
121
- //Only migrate if we haven't migrated yet
122
- if(isset($opts['current_item_linked']))
123
- {
124
- //Loop through the old options, migrate some of them
125
- foreach($opts as $option => $value)
126
- {
127
- //Handle all of our boolean options first, they're real easy, just add a 'b'
128
- if(strpos($option, 'display') > 0 || $option == 'current_item_linked')
129
- {
130
- $this->breadcrumb_trail->opt['b' . $option] = $value;
131
- }
132
- //Handle migration of anchor templates to the templates
133
- else if(strpos($option, 'anchor') > 0)
134
- {
135
- $parts = explode('_', $option);
136
- //Do excess slash removal sanitation
137
- $this->breadcrumb_trail->opt['H' . $parts[0] . '_template'] = $value . '%htitle%</a>';
138
- }
139
- //Handle our abs integers
140
- else if($option == 'max_title_length' || $option == 'post_post_root' || $option == 'post_page_root')
141
- {
142
- $this->breadcrumb_trail->opt['a' . $option] = $value;
143
- }
144
- //Now everything else, minus prefix and suffix
145
- else if(strpos($option, 'prefix') === false && strpos($option, 'suffix') === false)
146
- {
147
- $this->breadcrumb_trail->opt['S' . $option] = $value;
148
- }
149
- }
150
- }
151
- //Add in the new settings for CPTs introduced in 4.0
152
- foreach($wp_post_types as $post_type)
153
- {
154
- //We only want custom post types
155
- if(!$post_type->_builtin)
156
- {
157
- //Add in the archive_display option
158
- $this->breadcrumb_trail->opt['bpost_' . $post_type->name . '_archive_display'] = $post_type->has_archive;
159
- }
160
- }
161
- $opts = $this->breadcrumb_trail->opt;
162
- }
163
- if(version_compare($version, '4.0.1', '<'))
164
- {
165
- if(isset($opts['Hcurrent_item_template_no_anchor']))
166
- {
167
- unset($opts['Hcurrent_item_template_no_anchor']);
168
- }
169
- if(isset($opts['Hcurrent_item_template']))
170
- {
171
- unset($opts['Hcurrent_item_template']);
172
- }
173
- }
174
- //Upgrading to 4.3.0
175
- if(version_compare($version, '4.3.0', '<'))
176
- {
177
- //Removed home_title
178
- if(isset($opts['Shome_title']))
179
- {
180
- unset($opts['Shome_title']);
181
- }
182
- //Removed mainsite_title
183
- if(isset($opts['Smainsite_title']))
184
- {
185
- unset($opts['Smainsite_title']);
186
- }
187
- }
188
- //Upgrading to 5.1.0
189
- if(version_compare($version, '5.1.0', '<'))
190
- {
191
- foreach($wp_taxonomies as $taxonomy)
192
- {
193
- //If we have the old options style for it, update
194
- if($taxonomy->name !== 'post_format' && isset($opts['H' . $taxonomy->name . '_template']))
195
- {
196
- //Migrate to the new setting name
197
- $opts['Htax_' . $taxonomy->name . '_template'] = $opts['H' . $taxonomy->name . '_template'];
198
- $opts['Htax_' . $taxonomy->name . '_template_no_anchor'] = $opts['H' . $taxonomy->name . '_template_no_anchor'];
199
- //Clean up old settings
200
- unset($opts['H' . $taxonomy->name . '_template']);
201
- unset($opts['H' . $taxonomy->name . '_template_no_anchor']);
202
- }
203
- }
204
- }
205
- //Upgrading to 5.4.0
206
- if(version_compare($version, '5.4.0', '<'))
207
- {
208
- //Migrate users to schema.org breadcrumbs for author and search if still on the defaults for posts
209
- if($opts['Hpost_post_template'] === bcn_breadcrumb::get_default_template() && $opts['Hpost_post_template_no_anchor'] === bcn_breadcrumb::default_template_no_anchor)
210
- {
211
- if($opts['Hpaged_template'] === 'Page %htitle%')
212
- {
213
- $opts['Hpaged_template'] = $this->opt['Hpaged_template'];
214
- }
215
- if($opts['Hsearch_template'] === 'Search results for &#39;<a title="Go to the first page of search results for %title%." href="%link%" class="%type%">%htitle%</a>&#39;' || $opts['Hsearch_template'] === 'Search results for &#039;<a title="Go to the first page of search results for %title%." href="%link%" class="%type%">%htitle%</a>&#039;')
216
- {
217
- $opts['Hsearch_template'] = $this->opt['Hsearch_template'];
218
- }
219
- if($opts['Hsearch_template_no_anchor'] === 'Search results for &#39;%htitle%&#39;' || $opts['Hsearch_template_no_anchor'] === 'Search results for &#039;%htitle%&#039;')
220
- {
221
- $opts['Hsearch_template_no_anchor'] = $this->opt['Hsearch_template_no_anchor'];
222
- }
223
- if($opts['Hauthor_template'] === 'Articles by: <a title="Go to the first page of posts by %title%." href="%link%" class="%type%">%htitle%</a>')
224
- {
225
- $opts['Hauthor_template'] = $this->opt['Hauthor_template'];
226
- }
227
- if($opts['Hauthor_template_no_anchor'] === 'Articles by: %htitle%')
228
- {
229
- $opts['Hauthor_template_no_anchor'] = $this->opt['Hauthor_template_no_anchor'];
230
- }
231
- }
232
- }
233
- //Upgrading to 5.5.0
234
- if(version_compare($version, '5.5.0', '<'))
235
- {
236
- //Translate the old 'page' taxonomy type to BCN_POST_PARENT
237
- if($this->opt['Spost_post_taxonomy_type'] === 'page')
238
- {
239
- $this->opt['Spost_post_taxonomy_type'] = 'BCN_POST_PARENT';
240
- }
241
- if(!isset($this->opt['Spost_post_taxonomy_referer']))
242
- {
243
- $this->opt['bpost_post_taxonomy_referer'] = false;
244
- }
245
- //Loop through all of the post types in the array
246
- foreach($wp_post_types as $post_type)
247
- {
248
- //Check for non-public CPTs
249
- if(!apply_filters('bcn_show_cpt_private', $post_type->public, $post_type->name))
250
- {
251
- continue;
252
- }
253
- //We only want custom post types
254
- if(!$post_type->_builtin)
255
- {
256
- //Translate the old 'page' taxonomy type to BCN_POST_PARENT
257
- if($this->opt['Spost_' . $post_type->name . '_taxonomy_type'] === 'page')
258
- {
259
- $this->opt['Spost_' . $post_type->name . '_taxonomy_type'] = 'BCN_POST_PARENT';
260
- }
261
- //Translate the old 'date' taxonomy type to BCN_DATE
262
- if($this->opt['Spost_' . $post_type->name . '_taxonomy_type'] === 'date')
263
- {
264
- $this->opt['Spost_' . $post_type->name . '_taxonomy_type'] = 'BCN_DATE';
265
- }
266
- if(!isset($this->opt['Spost_' . $post_type->name . '_taxonomy_referer']))
267
- {
268
- $this->opt['bpost_' . $post_type->name . '_taxonomy_referer'] = false;
269
- }
270
- }
271
- }
272
- }
273
- //Upgrading to 6.0.0
274
- if(version_compare($version, '6.0.0', '<'))
275
- {
276
- //Loop through all of the post types in the array
277
- foreach($wp_post_types as $post_type)
278
- {
279
- if(isset($this->opt['Spost_' . $post_type->name . '_taxonomy_type']))
280
- {
281
- $this->opt['Spost_' . $post_type->name . '_hierarchy_type'] = $this->opt['Spost_' . $post_type->name . '_taxonomy_type'];
282
- unset($this->opt['Spost_' . $post_type->name . '_taxonomy_type']);
283
- }
284
- if(isset($this->opt['Spost_' . $post_type->name . '_taxonomy_display']))
285
- {
286
- $this->opt['Spost_' . $post_type->name . '_hierarchy_display'] = $this->opt['Spost_' . $post_type->name . '_taxonomy_display'];
287
- unset($this->opt['Spost_' . $post_type->name . '_taxonomy_display']);
288
- }
289
- }
290
- }
291
- //Set the max title length to 20 if we are not limiting the title and the length was 0
292
- if(!$opts['blimit_title'] && $opts['amax_title_length'] == 0)
293
- {
294
- $opts['amax_title_length'] = 20;
295
- }
296
  }
297
  //Save the passed in opts to the object's option array
298
- $this->opt = mtekk_adminKit::parse_args($opts, $this->opt);
299
- //End with resetting up the options
300
- breadcrumb_navxt::setup_options($this->opt);
301
- }
302
- function opts_update_prebk(&$opts)
303
- {
304
- //This may no longer be needed
305
- breadcrumb_navxt::setup_options($opts);
306
- $opts = apply_filters('bcn_opts_update_prebk', $opts);
307
  }
308
  /**
309
  * help action hook function
@@ -324,12 +158,19 @@ class bcn_admin extends mtekk_adminKit
324
  {
325
  $general_tab = '<p>' . esc_html__('Tips for the settings are located below select options.', 'breadcrumb-navxt') .
326
  '</p><h5>' . esc_html__('Resources', 'breadcrumb-navxt') . '</h5><ul><li>' .
327
- sprintf(esc_html__("%sTutorials and How Tos%s: There are several guides, tutorials, and how tos available on the author's website.", 'breadcrumb-navxt'),'<a title="' . esc_attr__('Go to the Breadcrumb NavXT tag archive.', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/tag/breadcrumb-navxt">', '</a>') . '</li><li>' .
328
- sprintf(esc_html__('%sOnline Documentation%s: Check out the documentation for more indepth technical information.', 'breadcrumb-navxt'), '<a title="' . esc_attr__('Go to the Breadcrumb NavXT online documentation', 'breadcrumb-navxt') . '" href="https://mtekk.us/code/breadcrumb-navxt/breadcrumb-navxt-doc/">', '</a>') . '</li><li>' .
329
- sprintf(esc_html__('%sReport a Bug%s: If you think you have found a bug, please include your WordPress version and details on how to reproduce the bug.', 'breadcrumb-navxt'),'<a title="' . esc_attr__('Go to the Breadcrumb NavXT support post for your version.', 'breadcrumb-navxt') . '" href="https://wordpress.org/support/plugin/breadcrumb-navxt/">', '</a>') . '</li></ul>' .
 
 
 
 
330
  '<h5>' . esc_html__('Giving Back', 'breadcrumb-navxt') . '</h5><ul><li>' .
331
- sprintf(esc_html__('%sDonate%s: Love Breadcrumb NavXT and want to help development? Consider buying the author a beer.', 'breadcrumb-navxt'),'<a title="' . esc_attr__('Go to PayPal to give a donation to Breadcrumb NavXT.', 'breadcrumb-navxt') . '" href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=FD5XEU783BR8U&lc=US&item_name=Breadcrumb%20NavXT%20Donation&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">', '</a>') . '</li><li>' .
332
- sprintf(esc_html__('%sTranslate%s: Is your language not available? Visit the Breadcrumb NavXT translation project on WordPress.org to start translating.', 'breadcrumb-navxt'),'<a title="' . esc_attr__('Go to the Breadcrumb NavXT translation project.', 'breadcrumb-navxt') . '" href="https://translate.wordpress.org/projects/wp-plugins/breadcrumb-navxt">', '</a>') . '</li></ul>';
 
 
 
333
 
334
  $screen->add_help_tab(
335
  array(
@@ -418,20 +259,20 @@ class bcn_admin extends mtekk_adminKit
418
  }
419
  else if(defined('BCN_SETTINGS_USE_NETWORK') && BCN_SETTINGS_USE_NETWORK)
420
  {
421
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Your network settings will override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_nsiteoveride');
422
  }
423
  else if(defined('BCN_SETTINGS_FAVOR_LOCAL') && BCN_SETTINGS_FAVOR_LOCAL)
424
  {
425
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Your network settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_isitemayoveride');
426
  }
427
  else if(defined('BCN_SETTINGS_FAVOR_NETWORK') && BCN_SETTINGS_FAVOR_NETWORK)
428
  {
429
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Your network settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_nsitemayoveride');
430
  }
431
  //Fall through if no settings mode was set
432
  else
433
  {
434
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: No BCN_SETTINGS_* define statement found, defaulting to BCN_SETTINGS_USE_LOCAL.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_nosetting');
435
  }
436
  }
437
  }
@@ -441,9 +282,44 @@ class bcn_admin extends mtekk_adminKit
441
  function deprecated_settings_warn()
442
  {
443
  //We're deprecating the limit title length setting, let the user know the new method of accomplishing this
444
- if(isset($this->opt['blimit_title']) && $this->opt['blimit_title'])
445
  {
446
- $this->messages[] = new mtekk_adminKit_message(sprintf(esc_html__('Warning: Your are using a deprecated setting "Title Length" (see Miscellaneous &gt; Deprecated), please %1$suse CSS instead%2$s.', 'breadcrumb-navxt'), '<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>'), 'warning');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  }
448
  }
449
  /**
@@ -475,7 +351,7 @@ class bcn_admin extends mtekk_adminKit
475
  $this->deprecated_settings_warn();
476
  //Do a check for multisite settings mode
477
  $this->multisite_settings_warn();
478
- do_action($this->unique_prefix . '_settings_pre_messages', $this->opt);
479
  //Display our messages
480
  $this->messages();
481
  ?>
@@ -495,97 +371,48 @@ class bcn_admin extends mtekk_adminKit
495
  <h2><?php _e('General', 'breadcrumb-navxt'); ?></h2>
496
  <table class="form-table">
497
  <?php
498
- $this->textbox(__('Breadcrumb Separator', 'breadcrumb-navxt'), 'hseparator', '2', false, __('Placed in between each breadcrumb.', 'breadcrumb-navxt'));
499
- do_action($this->unique_prefix . '_settings_general', $this->opt);
500
  ?>
501
  </table>
502
  <h2><?php _e('Current Item', 'breadcrumb-navxt'); ?></h2>
503
  <table class="form-table adminkit-enset-top">
504
  <?php
505
- $this->input_check(__('Link Current Item', 'breadcrumb-navxt'), 'bcurrent_item_linked', __('Yes', 'breadcrumb-navxt'));
506
- $this->input_check(_x('Paged Breadcrumb', 'Paged as in when on an archive or post that is split into multiple pages', 'breadcrumb-navxt'), 'bpaged_display', __('Place the page number breadcrumb in the trail.', 'breadcrumb-navxt'), false, __('Indicates that the user is on a page other than the first of a paginated archive or post.', 'breadcrumb-navxt'), 'adminkit-enset-ctrl adminkit-enset');
507
- $this->textbox(_x('Paged Template', 'Paged as in when on an archive or post that is split into multiple pages', 'breadcrumb-navxt'), 'Hpaged_template', '4', false, __('The template for paged breadcrumbs.', 'breadcrumb-navxt'), 'adminkit-enset');
508
- do_action($this->unique_prefix . '_settings_current_item', $this->opt);
509
  ?>
510
  </table>
511
  <h2><?php _e('Home Breadcrumb', 'breadcrumb-navxt'); ?></h2>
512
  <table class="form-table adminkit-enset-top">
513
  <?php
514
- $this->input_check(__('Home Breadcrumb', 'breadcrumb-navxt'), 'bhome_display', __('Place the home breadcrumb in the trail.', 'breadcrumb-navxt'), false, '', 'adminkit-enset-ctrl adminkit-enset');
515
- $this->textbox(__('Home Template', 'breadcrumb-navxt'), 'Hhome_template', '6', false, __('The template for the home breadcrumb.', 'breadcrumb-navxt'), 'adminkit-enset');
516
- $this->textbox(__('Home Template (Unlinked)', 'breadcrumb-navxt'), 'Hhome_template_no_anchor', '4', false, __('The template for the home breadcrumb, used when the breadcrumb is not linked.', 'breadcrumb-navxt'), 'adminkit-enset');
517
- do_action($this->unique_prefix . '_settings_home', $this->opt);
518
  ?>
519
  </table>
520
  <h2><?php _e('Blog Breadcrumb', 'breadcrumb-navxt'); ?></h2>
521
  <table class="form-table adminkit-enset-top">
522
  <?php
523
- $this->input_check(__('Blog Breadcrumb', 'breadcrumb-navxt'), 'bblog_display', __('Place the blog breadcrumb in the trail.', 'breadcrumb-navxt'), $this->maybe_disable_blog_options(), '', 'adminkit-enset-ctrl adminkit-enset');
524
- do_action($this->unique_prefix . '_settings_blog', $this->opt);
525
  ?>
526
  </table>
527
  <h2><?php _e('Mainsite Breadcrumb', 'breadcrumb-navxt'); ?></h2>
528
  <table class="form-table adminkit-enset-top">
529
  <?php
530
- $this->input_check(__('Main Site Breadcrumb', 'breadcrumb-navxt'), 'bmainsite_display', __('Place the main site home breadcrumb in the trail in an multisite setup.', 'breadcrumb-navxt'), $this->maybe_disable_mainsite_options(), '', 'adminkit-enset-ctrl adminkit-enset');
531
- $this->textbox(__('Main Site Home Template', 'breadcrumb-navxt'), 'Hmainsite_template', '6', $this->maybe_disable_mainsite_options(), __('The template for the main site home breadcrumb, used only in multisite environments.', 'breadcrumb-navxt'), 'adminkit-enset');
532
- $this->textbox(__('Main Site Home Template (Unlinked)', 'breadcrumb-navxt'), 'Hmainsite_template_no_anchor', '4', $this->maybe_disable_mainsite_options(), __('The template for the main site home breadcrumb, used only in multisite environments and when the breadcrumb is not linked.', 'breadcrumb-navxt'), 'adminkit-enset');
533
- do_action($this->unique_prefix . '_settings_mainsite', $this->opt);
534
  ?>
535
  </table>
536
- <?php do_action($this->unique_prefix . '_after_settings_tab_general', $this->opt); ?>
537
  </fieldset>
538
  <fieldset id="post" class="bcn_options">
539
  <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>
540
- <h2><?php _e('Posts', 'breadcrumb-navxt'); ?></h2>
541
- <table class="form-table adminkit-enset-top">
542
- <?php
543
- $this->textbox(__('Post Template', 'breadcrumb-navxt'), 'Hpost_post_template', '6', false, __('The template for post breadcrumbs.', 'breadcrumb-navxt'));
544
- $this->textbox(__('Post Template (Unlinked)', 'breadcrumb-navxt'), 'Hpost_post_template_no_anchor', '4', false, __('The template for post breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
545
- $this->input_check(__('Post Hierarchy Display', 'breadcrumb-navxt'), 'bpost_post_hierarchy_display', __('Show the hierarchy (specified below) leading to a post in the breadcrumb trail.', 'breadcrumb-navxt'), false, '', 'adminkit-enset-ctrl adminkit-enset');
546
- $this->input_check(__('Post Hierarchy Use Parent First', 'breadcrumb-navxt'), 'bpost_post_hierarchy_parent_first', __('Use the parent of the post as the primary hierarchy, falling back to the hierarchy selected below when the parent hierarchy is exhausted.', 'breadcrumb-navxt'), false, '', 'adminkit-enset');
547
- $this->input_check(__('Post Hierarchy Referer Influence', 'breadcrumb-navxt'), 'bpost_post_taxonomy_referer', __('Allow the referring page to influence the taxonomy selected for the hierarchy.', 'breadcrumb-navxt'), false, '', 'adminkit-enset');
548
- ?>
549
- <tr valign="top">
550
- <th scope="row">
551
- <?php _e('Post Hierarchy', 'breadcrumb-navxt'); ?>
552
- </th>
553
- <td>
554
- <?php
555
- $this->input_radio('Spost_post_hierarchy_type', 'category', __('Categories'), false, 'adminkit-enset');
556
- $this->input_radio('Spost_post_hierarchy_type', 'BCN_DATE', __('Dates', 'breadcrumb-navxt'), false, 'adminkit-enset');
557
- $this->input_radio('Spost_post_hierarchy_type', 'post_tag', __('Tags'), false, 'adminkit-enset');
558
- //We use the value 'page' but really, this will follow the parent post hierarchy
559
- $this->input_radio('Spost_post_hierarchy_type', 'BCN_POST_PARENT', __('Post Parent', 'breadcrumb-navxt'), false, 'adminkit-enset');
560
- //Loop through all of the taxonomies in the array
561
- foreach($wp_taxonomies as $taxonomy)
562
- {
563
- //Check for non-public taxonomies
564
- if(!apply_filters('bcn_show_tax_private', $taxonomy->public, $taxonomy->name, 'post'))
565
- {
566
- continue;
567
- }
568
- //We only want custom taxonomies
569
- if(($taxonomy->object_type == 'post' || is_array($taxonomy->object_type) && in_array('post', $taxonomy->object_type)) && !$taxonomy->_builtin)
570
- {
571
- $this->input_radio('Spost_post_hierarchy_type', $taxonomy->name, mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8'), false, 'adminkit-enset');
572
- }
573
- }
574
- ?>
575
- <p class="description"><?php 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'); ?></p>
576
- </td>
577
- </tr>
578
- </table>
579
- <h2><?php _e('Pages', 'breadcrumb-navxt'); ?></h2>
580
- <table class="form-table">
581
- <?php
582
- $this->textbox(__('Page Template', 'breadcrumb-navxt'), 'Hpost_page_template', '6', false, __('The template for page breadcrumbs.', 'breadcrumb-navxt'));
583
- $this->textbox(__('Page Template (Unlinked)', 'breadcrumb-navxt'), 'Hpost_page_template_no_anchor', '4', false, __('The template for page breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
584
- $this->input_hidden('bpost_page_hierarchy_display');
585
- $this->input_hidden('bpost_page_hierarchy_parent_first');
586
- $this->input_hidden('Spost_page_hierarchy_type');
587
- ?>
588
- </table>
589
  <?php
590
  //Loop through all of the post types in the array
591
  foreach($wp_post_types as $post_type)
@@ -595,31 +422,33 @@ class bcn_admin extends mtekk_adminKit
595
  {
596
  continue;
597
  }
598
- //We only want custom post types
599
- if($post_type->name === 'attachment' || !$post_type->_builtin)
600
- {
601
- $singular_name_lc = mb_strtolower($post_type->labels->singular_name, 'UTF-8');
602
  ?>
603
  <h2><?php echo $post_type->labels->singular_name; ?></h2>
604
  <table class="form-table adminkit-enset-top">
605
  <?php
606
- $this->textbox(sprintf(__('%s Template', 'breadcrumb-navxt'), $post_type->labels->singular_name), 'Hpost_' . $post_type->name . '_template', '6', false, sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt'), $singular_name_lc));
607
- $this->textbox(sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $post_type->labels->singular_name), 'Hpost_' . $post_type->name . '_template_no_anchor', '4', false, sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'), $singular_name_lc));
608
- $optid = mtekk_adminKit::get_valid_id('apost_' . $post_type->name . '_root');
 
 
609
  ?>
610
  <tr valign="top">
611
  <th scope="row">
612
  <label for="<?php echo $optid;?>"><?php printf(esc_html__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name);?></label>
613
  </th>
614
  <td>
615
- <?php wp_dropdown_pages(array('name' => $this->unique_prefix . '_options[apost_' . $post_type->name . '_root]', 'id' => $optid, 'echo' => 1, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => $this->opt['apost_' . $post_type->name . '_root']));?>
616
  </td>
617
  </tr>
618
  <?php
619
- $this->input_check(sprintf(__('%s Archive Display', 'breadcrumb-navxt'), $post_type->labels->singular_name), 'bpost_' . $post_type->name . '_archive_display', sprintf(__('Show the breadcrumb for the %s post type archives in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc), !$post_type->has_archive);
620
- $this->input_check(sprintf(__('%s Hierarchy Display', 'breadcrumb-navxt'), $post_type->labels->singular_name), 'bpost_' . $post_type->name . '_hierarchy_display', sprintf(__('Show the hierarchy (specified below) leading to a %s in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc), false, '', 'adminkit-enset-ctrl adminkit-enset');
621
- $this->input_check(sprintf(__('%s Hierarchy Use Parent First', 'breadcrumb-navxt'), $post_type->labels->singular_name), 'bpost_' . $post_type->name . '_hierarchy_parent_first', 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), false, '', 'adminkit-enset');
622
- $this->input_check(sprintf(__('%s Hierarchy Referer Influence', 'breadcrumb-navxt'), $post_type->labels->singular_name), 'bpost_' . $post_type->name . '_taxonomy_referer', __('Allow the referring page to influence the taxonomy selected for the hierarchy.', 'breadcrumb-navxt'), false, '', 'adminkit-enset');
 
 
 
623
  ?>
624
  <tr valign="top">
625
  <th scope="row">
@@ -628,8 +457,8 @@ class bcn_admin extends mtekk_adminKit
628
  <td>
629
  <?php
630
  //We use the value 'page' but really, this will follow the parent post hierarchy
631
- $this->input_radio('Spost_' . $post_type->name . '_hierarchy_type', 'BCN_POST_PARENT', __('Post Parent', 'breadcrumb-navxt'), false, 'adminkit-enset');
632
- $this->input_radio('Spost_' . $post_type->name . '_hierarchy_type', 'BCN_DATE', __('Dates', 'breadcrumb-navxt'), false, 'adminkit-enset');
633
  //Loop through all of the taxonomies in the array
634
  foreach($wp_taxonomies as $taxonomy)
635
  {
@@ -641,7 +470,7 @@ class bcn_admin extends mtekk_adminKit
641
  //We only want custom taxonomies
642
  if($taxonomy->object_type == $post_type->name || in_array($post_type->name, $taxonomy->object_type))
643
  {
644
- $this->input_radio('Spost_' . $post_type->name . '_hierarchy_type', $taxonomy->name, $taxonomy->labels->singular_name, false, 'adminkit-enset');
645
  }
646
  }
647
  ?>
@@ -659,11 +488,13 @@ class bcn_admin extends mtekk_adminKit
659
  </p>
660
  </td>
661
  </tr>
662
- </table>
663
  <?php
664
- }
 
 
 
665
  }
666
- do_action($this->unique_prefix . '_after_settings_tab_post', $this->opt);
667
  ?>
668
  </fieldset>
669
  <fieldset id="tax" class="bcn_options alttab">
@@ -671,22 +502,22 @@ class bcn_admin extends mtekk_adminKit
671
  <h2><?php _e('Categories', 'breadcrumb-navxt'); ?></h2>
672
  <table class="form-table">
673
  <?php
674
- $this->textbox(__('Category Template', 'breadcrumb-navxt'), 'Htax_category_template', '6', false, __('The template for category breadcrumbs.', 'breadcrumb-navxt'));
675
- $this->textbox(__('Category Template (Unlinked)', 'breadcrumb-navxt'), 'Htax_category_template_no_anchor', '4', false, __('The template for category breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
676
  ?>
677
  </table>
678
  <h2><?php _e('Tags', 'breadcrumb-navxt'); ?></h2>
679
  <table class="form-table">
680
  <?php
681
- $this->textbox(__('Tag Template', 'breadcrumb-navxt'), 'Htax_post_tag_template', '6', false, __('The template for tag breadcrumbs.', 'breadcrumb-navxt'));
682
- $this->textbox(__('Tag Template (Unlinked)', 'breadcrumb-navxt'), 'Htax_post_tag_template_no_anchor', '4', false, __('The template for tag breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
683
  ?>
684
  </table>
685
  <h2><?php _e('Post Formats', 'breadcrumb-navxt'); ?></h2>
686
  <table class="form-table">
687
  <?php
688
- $this->textbox(__('Post Format Template', 'breadcrumb-navxt'), 'Htax_post_format_template', '6', false, __('The template for post format breadcrumbs.', 'breadcrumb-navxt'));
689
- $this->textbox(__('Post Format Template (Unlinked)', 'breadcrumb-navxt'), 'Htax_post_format_template_no_anchor', '4', false, __('The template for post_format breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
690
  ?>
691
  </table>
692
  <?php
@@ -706,43 +537,43 @@ class bcn_admin extends mtekk_adminKit
706
  <h3><?php echo mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8'); ?></h3>
707
  <table class="form-table">
708
  <?php
709
- $this->textbox(sprintf(__('%s Template', 'breadcrumb-navxt'), $taxonomy->labels->singular_name), 'Htax_' . $taxonomy->name . '_template', '6', false, sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt'), $label_lc));
710
- $this->textbox(sprintf(__('%s Template (Unlinked)', 'breadcrumb-navxt'), $taxonomy->labels->singular_name), 'Htax_' . $taxonomy->name . '_template_no_anchor', '4', false, sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'), $label_lc));
711
  ?>
712
  </table>
713
  <?php
714
  }
715
  }
716
- do_action($this->unique_prefix . '_after_settings_tab_taxonomy', $this->opt); ?>
717
  </fieldset>
718
  <fieldset id="miscellaneous" class="bcn_options">
719
  <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>
720
  <h2><?php _e('Author Archives', 'breadcrumb-navxt'); ?></h2>
721
  <table class="form-table">
722
  <?php
723
- $this->textbox(__('Author Template', 'breadcrumb-navxt'), 'Hauthor_template', '6', false, __('The template for author breadcrumbs.', 'breadcrumb-navxt'));
724
- $this->textbox(__('Author Template (Unlinked)', 'breadcrumb-navxt'), 'Hauthor_template_no_anchor', '4', false, __('The template for author breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
725
- $this->input_select(__('Author Display Format', 'breadcrumb-navxt'), 'Sauthor_name', array("display_name", "nickname", "first_name", "last_name"), false, __('display_name uses the name specified in "Display name publicly as" under the user profile the others correspond to options in the user profile.', 'breadcrumb-navxt'));
726
- $optid = mtekk_adminKit::get_valid_id('aauthor_root');
727
  ?>
728
  <tr valign="top">
729
  <th scope="row">
730
  <label for="<?php echo $optid;?>"><?php esc_html_e('Author Root Page', 'breadcrumb-navxt');?></label>
731
  </th>
732
  <td>
733
- <?php wp_dropdown_pages(array('name' => $this->unique_prefix . '_options[aauthor_root]', 'id' => $optid, 'echo' => 1, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => $this->opt['aauthor_root']));?>
734
  </td>
735
  </tr>
736
  </table>
737
  <h2><?php _e('Miscellaneous', 'breadcrumb-navxt'); ?></h2>
738
  <table class="form-table">
739
  <?php
740
- $this->textbox(__('Date Template', 'breadcrumb-navxt'), 'Hdate_template', '6', false, __('The template for date breadcrumbs.', 'breadcrumb-navxt'));
741
- $this->textbox(__('Date Template (Unlinked)', 'breadcrumb-navxt'), 'Hdate_template_no_anchor', '4', false, __('The template for date breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
742
- $this->textbox(__('Search Template', 'breadcrumb-navxt'), 'Hsearch_template', '6', false, __('The anchor template for search breadcrumbs, used only when the search results span several pages.', 'breadcrumb-navxt'));
743
- $this->textbox(__('Search Template (Unlinked)', 'breadcrumb-navxt'), 'Hsearch_template_no_anchor', '4', false, __('The anchor template for search breadcrumbs, used only when the search results span several pages and the breadcrumb is not linked.', 'breadcrumb-navxt'));
744
- $this->input_text(__('404 Title', 'breadcrumb-navxt'), 'S404_title', 'regular-text');
745
- $this->textbox(__('404 Template', 'breadcrumb-navxt'), 'H404_template', '4', false, __('The template for 404 breadcrumbs.', 'breadcrumb-navxt'));
746
  ?>
747
  </table>
748
  <h2><?php _e('Deprecated', 'breadcrumb-navxt'); ?></h2>
@@ -753,23 +584,23 @@ class bcn_admin extends mtekk_adminKit
753
  </th>
754
  <td>
755
  <label>
756
- <input name="bcn_options[blimit_title]" type="checkbox" id="blimit_title" value="true" <?php checked(true, $this->opt['blimit_title']); ?> />
757
  <?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>');?>
758
  </label><br />
759
  <ul>
760
  <li>
761
  <label for="amax_title_length">
762
  <?php esc_html_e('Max Title Length: ','breadcrumb-navxt');?>
763
- <input type="number" name="bcn_options[amax_title_length]" id="amax_title_length" min="1" step="1" value="<?php echo esc_html($this->opt['amax_title_length'], ENT_COMPAT, 'UTF-8'); ?>" class="small-text" />
764
  </label>
765
  </li>
766
  </ul>
767
  </td>
768
  </tr>
769
  </table>
770
- <?php do_action($this->unique_prefix . '_after_settings_tab_miscellaneous', $this->opt); ?>
771
  </fieldset>
772
- <?php do_action($this->unique_prefix . '_after_settings_tabs', $this->opt); ?>
773
  </div>
774
  <p class="submit"><input type="submit" class="button-primary" name="bcn_admin_options" value="<?php esc_attr_e('Save Changes') ?>" /></p>
775
  </form>
1
  <?php
2
  /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
33
  return;
34
  }
35
  //Include admin base class
36
+ if(!class_exists('\mtekk\adminKit\adminKit'))
37
  {
38
+ require_once(dirname(__FILE__) . '/includes/adminKit/class-mtekk_adminkit.php');
39
  }
40
+ use mtekk\adminKit\{adminKit, form, message, setting};
41
  /**
42
  * The administrative interface class
43
  *
44
  */
45
+ class bcn_admin extends adminKit
46
  {
47
+ const version = '7.0.0';
48
  protected $full_name = 'Breadcrumb NavXT Settings';
49
  protected $short_name = 'Breadcrumb NavXT';
50
  protected $access_level = 'bcn_manage_options';
52
  protected $unique_prefix = 'bcn';
53
  protected $plugin_basename = null;
54
  protected $support_url = 'https://wordpress.org/support/plugin/breadcrumb-navxt/';
 
55
  /**
56
  * Administrative interface class default constructor
57
  *
58
+ * @param array $opts The breadcrumb trail object's settings array
59
  * @param string $basename The basename of the plugin
60
+ * @param array $settings The array of settings objects
61
  */
62
+ function __construct(array &$opts, $basename, array &$settings)
63
  {
 
64
  $this->plugin_basename = $basename;
65
  $this->full_name = esc_html__('Breadcrumb NavXT Settings', 'breadcrumb-navxt');
66
+ $this->settings =& $settings;
67
+ $this->opt =& $opts;
68
  //We're going to make sure we load the parent's constructor
69
  parent::__construct();
70
  }
71
+ /**
72
+ * Loads opts array values into the local settings array
73
+ *
74
+ * @param array $opts The opts array
75
+ */
76
+ function setting_merge($opts)
77
+ {
78
+ $unknown = array();
79
+ foreach($opts as $key => $value)
80
+ {
81
+ if(isset($this->settings[$key]) && $this->settings[$key] instanceof setting\setting)
82
+ {
83
+ $this->settings[$key]->set_value($this->settings[$key]->validate($value));
84
+ }
85
+ else if(isset($this->settings[$key]) && is_array($this->settings[$key]) && is_array($value))
86
+ {
87
+ foreach($value as $subkey => $subvalue)
88
+ {
89
+ if(isset($this->settings[$key][$subkey]) && $this->settings[$key][$subkey]instanceof setting\setting)
90
+ {
91
+ $this->settings[$key][$subkey]->set_value($this->settings[$key][$subkey]->validate($subvalue));
92
+ }
93
+ }
94
+ }
95
+ else
96
+ {
97
+ $unknown[] = $key;
98
+ }
99
+ }
100
+ //Add a message if we found some unknown settings while merging
101
+ if(count($unknown) > 0)
102
+ {
103
+ $this->messages[] = new message(
104
+ sprintf(__('Found %u unknown legacy settings: %s','breadcrumb-navxt'), count($unknown), implode(', ', $unknown)),
105
+ 'warning',
106
+ true,
107
+ 'bcn_unkonwn_legacy_settings');
108
+ }
109
+ }
110
  /**
111
  * admin initialization callback function
112
  *
119
  {
120
  //We're going to make sure we run the parent's version of this function as well
121
  parent::init();
122
+ $this->setting_merge($this->opt);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  }
124
  /**
125
  * Upgrades input options array, sets to $this->opt
129
  */
130
  function opts_upgrade($opts, $version)
131
  {
 
132
  //If our version is not the same as in the db, time to update
133
  if(version_compare($version, $this::version, '<'))
134
  {
135
+ require_once(dirname(__FILE__) . '/options_upgrade.php');
136
+ bcn_options_upgrade_handler($opts, $version, $this->opt);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
138
  //Save the passed in opts to the object's option array
139
+ //FIXME: Why do we do this?
140
+ $this->opt = adminKit::parse_args($opts, $this->opt);
 
 
 
 
 
 
 
141
  }
142
  /**
143
  * help action hook function
158
  {
159
  $general_tab = '<p>' . esc_html__('Tips for the settings are located below select options.', 'breadcrumb-navxt') .
160
  '</p><h5>' . esc_html__('Resources', 'breadcrumb-navxt') . '</h5><ul><li>' .
161
+ '<a title="' . esc_attr__('Go to the Breadcrumb NavXT tag archive.', 'breadcrumb-navxt') . '" href="https://mtekk.us/archives/tag/breadcrumb-navxt">' . esc_html__('Tutorials and How Tos', 'breadcrumb-navxt') . '</a>: ' .
162
+ esc_html__("There are several guides, tutorials, and how tos available on the author's website.", 'breadcrumb-navxt') . '</li><li>' .
163
+ '<a title="' . esc_attr__('Go to the Breadcrumb NavXT online documentation', 'breadcrumb-navxt') . '" href="https://mtekk.us/code/breadcrumb-navxt/breadcrumb-navxt-doc/">' . esc_html__('Online Documentation', 'breadcrumb-navxt') . '</a>: '.
164
+ esc_html__('Check out the documentation for more indepth technical information.', 'breadcrumb-navxt') . '</li><li>' .
165
+ '<a title="' . esc_attr__('Go to the Breadcrumb NavXT support post for your version.', 'breadcrumb-navxt') . '" href="https://wordpress.org/support/plugin/breadcrumb-navxt/">' . esc_html__('Report a Bug', 'breadcrumb-navxt') . '</a>: ' .
166
+ esc_html__('If you think you have found a bug, please include your WordPress version and details on how to reproduce the bug.', 'breadcrumb-navxt') . '</li></ul>' .
167
+
168
  '<h5>' . esc_html__('Giving Back', 'breadcrumb-navxt') . '</h5><ul><li>' .
169
+ '<a title="' . esc_attr__('Go to PayPal to give a donation to Breadcrumb NavXT.', 'breadcrumb-navxt') . '" href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=FD5XEU783BR8U&lc=US&item_name=Breadcrumb%20NavXT%20Donation&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted">' .
170
+ esc_html__('Donate', 'breadcrumb-navxt') . '</a>: ' .
171
+ esc_html__('Love Breadcrumb NavXT and want to help development? Consider buying the author a beer.', 'breadcrumb-navxt') . '</li><li>' .
172
+ '<a title="' . esc_attr__('Go to the Breadcrumb NavXT translation project.', 'breadcrumb-navxt') . '" href="https://translate.wordpress.org/projects/wp-plugins/breadcrumb-navxt">' . esc_html__('Translate', 'breadcrumb-navxt') . '</a>: ' .
173
+ esc_html__('Is your language not available? Visit the Breadcrumb NavXT translation project on WordPress.org to start translating.', 'breadcrumb-navxt') . '</li></ul>';
174
 
175
  $screen->add_help_tab(
176
  array(
259
  }
260
  else if(defined('BCN_SETTINGS_USE_NETWORK') && BCN_SETTINGS_USE_NETWORK)
261
  {
262
+ $this->messages[] = new message(esc_html__('Warning: Your network settings will override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_nsiteoveride');
263
  }
264
  else if(defined('BCN_SETTINGS_FAVOR_LOCAL') && BCN_SETTINGS_FAVOR_LOCAL)
265
  {
266
+ $this->messages[] = new message(esc_html__('Warning: Your network settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_isitemayoveride');
267
  }
268
  else if(defined('BCN_SETTINGS_FAVOR_NETWORK') && BCN_SETTINGS_FAVOR_NETWORK)
269
  {
270
+ $this->messages[] = new message(esc_html__('Warning: Your network settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_nsitemayoveride');
271
  }
272
  //Fall through if no settings mode was set
273
  else
274
  {
275
+ $this->messages[] = new message(esc_html__('Warning: No BCN_SETTINGS_* define statement found, defaulting to BCN_SETTINGS_USE_LOCAL.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_is_nosetting');
276
  }
277
  }
278
  }
282
  function deprecated_settings_warn()
283
  {
284
  //We're deprecating the limit title length setting, let the user know the new method of accomplishing this
285
+ if(isset($this->settings['blimit_title']) && $this->settings['blimit_title']->get_value())
286
  {
287
+ $this->messages[] = new message(
288
+ sprintf(
289
+ esc_html__('Error: The deprecated setting "Title Length" (see Miscellaneous &gt; Deprecated) has no effect in this version Breadcrumb NavXT. Please %1$suse CSS instead%2$s.', 'breadcrumb-navxt'),
290
+ '<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>'),
291
+ 'error');
292
+ }
293
+ foreach($this->settings as $key => $setting)
294
+ {
295
+ if($key[0] == "H" && substr_count($key, '_template') >= 1)
296
+ {
297
+ $deprecated_tags = array();
298
+ $replacement_tags = array();
299
+ //Deprecated ftitle check
300
+ if(substr_count($setting->get_value(), '%ftitle%') >= 1)
301
+ {
302
+ $deprecated_tags[] = '%ftitle%';
303
+ $replacement_tags[] = '%title%';
304
+ }
305
+ //Deprecated fhtitle check
306
+ if(substr_count($setting->get_value(), '%fhtitle%') >= 1)
307
+ {
308
+ $deprecated_tags[] = '%fhtitle%';
309
+ $replacement_tags[] = '%htitle%';
310
+ }
311
+ if(count($deprecated_tags) > 0)
312
+ {
313
+ $setting_link = sprintf('<a href="#%1$s">%2$s</a>', $key, $setting->get_title());
314
+ $this->messages[] = new message(
315
+ sprintf(
316
+ esc_html__('Error: The deprecated template tag %1$s found in setting %3$s. Please use %2$s instead.', 'breadcrumb-navxt'),
317
+ implode(' and ', $deprecated_tags),
318
+ implode(' and ', $replacement_tags),
319
+ $setting_link),
320
+ 'error');
321
+ }
322
+ }
323
  }
324
  }
325
  /**
351
  $this->deprecated_settings_warn();
352
  //Do a check for multisite settings mode
353
  $this->multisite_settings_warn();
354
+ do_action($this->unique_prefix . '_settings_pre_messages', $this->settings);
355
  //Display our messages
356
  $this->messages();
357
  ?>
371
  <h2><?php _e('General', 'breadcrumb-navxt'); ?></h2>
372
  <table class="form-table">
373
  <?php
374
+ $this->form->textbox($this->settings['hseparator'], '2', false, __('Placed in between each breadcrumb.', 'breadcrumb-navxt'));
375
+ do_action($this->unique_prefix . '_settings_general', $this->settings);
376
  ?>
377
  </table>
378
  <h2><?php _e('Current Item', 'breadcrumb-navxt'); ?></h2>
379
  <table class="form-table adminkit-enset-top">
380
  <?php
381
+ $this->form->input_check($this->settings['bcurrent_item_linked'], __('Yes', 'breadcrumb-navxt'));
382
+ $this->form->input_check($this->settings['bpaged_display'], __('Place the page number breadcrumb in the trail.', 'breadcrumb-navxt'), false, __('Indicates that the user is on a page other than the first of a paginated archive or post.', 'breadcrumb-navxt'), 'adminkit-enset-ctrl adminkit-enset');
383
+ $this->form->textbox($this->settings['Hpaged_template'], '4', false, __('The template for paged breadcrumbs.', 'breadcrumb-navxt'), 'adminkit-enset');
384
+ do_action($this->unique_prefix . '_settings_current_item', $this->settings);
385
  ?>
386
  </table>
387
  <h2><?php _e('Home Breadcrumb', 'breadcrumb-navxt'); ?></h2>
388
  <table class="form-table adminkit-enset-top">
389
  <?php
390
+ $this->form->input_check($this->settings['bhome_display'], __('Place the home breadcrumb in the trail.', 'breadcrumb-navxt'), false, '', 'adminkit-enset-ctrl adminkit-enset');
391
+ $this->form->textbox($this->settings['Hhome_template'], '6', false, __('The template for the home breadcrumb.', 'breadcrumb-navxt'), 'adminkit-enset');
392
+ $this->form->textbox($this->settings['Hhome_template_no_anchor'], '4', false, __('The template for the home breadcrumb, used when the breadcrumb is not linked.', 'breadcrumb-navxt'), 'adminkit-enset');
393
+ do_action($this->unique_prefix . '_settings_home', $this->settings);
394
  ?>
395
  </table>
396
  <h2><?php _e('Blog Breadcrumb', 'breadcrumb-navxt'); ?></h2>
397
  <table class="form-table adminkit-enset-top">
398
  <?php
399
+ $this->form->input_check($this->settings['bblog_display'], __('Place the blog breadcrumb in the trail.', 'breadcrumb-navxt'), $this->maybe_disable_blog_options(), '', 'adminkit-enset-ctrl adminkit-enset');
400
+ do_action($this->unique_prefix . '_settings_blog', $this->settings);
401
  ?>
402
  </table>
403
  <h2><?php _e('Mainsite Breadcrumb', 'breadcrumb-navxt'); ?></h2>
404
  <table class="form-table adminkit-enset-top">
405
  <?php
406
+ $this->form->input_check($this->settings['bmainsite_display'], __('Place the main site home breadcrumb in the trail in an multisite setup.', 'breadcrumb-navxt'), $this->maybe_disable_mainsite_options(), '', 'adminkit-enset-ctrl adminkit-enset');
407
+ $this->form->textbox($this->settings['Hmainsite_template'], '6', $this->maybe_disable_mainsite_options(), __('The template for the main site home breadcrumb, used only in multisite environments.', 'breadcrumb-navxt'), 'adminkit-enset');
408
+ $this->form->textbox($this->settings['Hmainsite_template_no_anchor'], '4', $this->maybe_disable_mainsite_options(), __('The template for the main site home breadcrumb, used only in multisite environments and when the breadcrumb is not linked.', 'breadcrumb-navxt'), 'adminkit-enset');
409
+ do_action($this->unique_prefix . '_settings_mainsite', $this->settings);
410
  ?>
411
  </table>
412
+ <?php do_action($this->unique_prefix . '_after_settings_tab_general', $this->settings); ?>
413
  </fieldset>
414
  <fieldset id="post" class="bcn_options">
415
  <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>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  <?php
417
  //Loop through all of the post types in the array
418
  foreach($wp_post_types as $post_type)
422
  {
423
  continue;
424
  }
425
+ $singular_name_lc = mb_strtolower($post_type->labels->singular_name, 'UTF-8');
 
 
 
426
  ?>
427
  <h2><?php echo $post_type->labels->singular_name; ?></h2>
428
  <table class="form-table adminkit-enset-top">
429
  <?php
430
+ $this->form->textbox($this->settings['Hpost_' . $post_type->name . '_template'], '6', false, sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt'), $singular_name_lc));
431
+ $this->form->textbox($this->settings['Hpost_' . $post_type->name . '_template_no_anchor'], '4', false, sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'), $singular_name_lc));
432
+ if(!in_array($post_type->name, array('page', 'post')))
433
+ {
434
+ $optid = form::get_valid_id('apost_' . $post_type->name . '_root');
435
  ?>
436
  <tr valign="top">
437
  <th scope="row">
438
  <label for="<?php echo $optid;?>"><?php printf(esc_html__('%s Root Page', 'breadcrumb-navxt'), $post_type->labels->singular_name);?></label>
439
  </th>
440
  <td>
441
+ <?php wp_dropdown_pages(array('name' => $this->unique_prefix . '_options[apost_' . $post_type->name . '_root]', 'id' => $optid, 'echo' => 1, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => $this->settings['apost_' . $post_type->name . '_root']->get_value()));?>
442
  </td>
443
  </tr>
444
  <?php
445
+ $this->form->input_check($this->settings['bpost_' . $post_type->name . '_archive_display'], sprintf(__('Show the breadcrumb for the %s post type archives in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc), !$post_type->has_archive);
446
+ }
447
+ if(!in_array($post_type->name, array('page')))
448
+ {
449
+ $this->form->input_check($this->settings['bpost_' . $post_type->name . '_hierarchy_display'], sprintf(__('Show the hierarchy (specified below) leading to a %s in the breadcrumb trail.', 'breadcrumb-navxt'), $singular_name_lc), false, '', 'adminkit-enset-ctrl adminkit-enset');
450
+ $this->form->input_check($this->settings['bpost_' . $post_type->name . '_hierarchy_parent_first'], 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), false, '', 'adminkit-enset');
451
+ $this->form->input_check($this->settings['bpost_' . $post_type->name . '_taxonomy_referer'], __('Allow the referring page to influence the taxonomy selected for the hierarchy.', 'breadcrumb-navxt'), false, '', 'adminkit-enset');
452
  ?>
453
  <tr valign="top">
454
  <th scope="row">
457
  <td>
458
  <?php
459
  //We use the value 'page' but really, this will follow the parent post hierarchy
460
+ $this->form->input_radio($this->settings['Epost_' . $post_type->name . '_hierarchy_type'], 'BCN_POST_PARENT', __('Post Parent', 'breadcrumb-navxt'), false, 'adminkit-enset');
461
+ $this->form->input_radio($this->settings['Epost_' . $post_type->name . '_hierarchy_type'], 'BCN_DATE', __('Dates', 'breadcrumb-navxt'), false, 'adminkit-enset');
462
  //Loop through all of the taxonomies in the array
463
  foreach($wp_taxonomies as $taxonomy)
464
  {
470
  //We only want custom taxonomies
471
  if($taxonomy->object_type == $post_type->name || in_array($post_type->name, $taxonomy->object_type))
472
  {
473
+ $this->form->input_radio($this->settings['Epost_' . $post_type->name . '_hierarchy_type'], $taxonomy->name, $taxonomy->labels->singular_name, false, 'adminkit-enset');
474
  }
475
  }
476
  ?>
488
  </p>
489
  </td>
490
  </tr>
 
491
  <?php
492
+ }
493
+ ?>
494
+ </table>
495
+ <?php
496
  }
497
+ do_action($this->unique_prefix . '_after_settings_tab_post', $this->settings);
498
  ?>
499
  </fieldset>
500
  <fieldset id="tax" class="bcn_options alttab">
502
  <h2><?php _e('Categories', 'breadcrumb-navxt'); ?></h2>
503
  <table class="form-table">
504
  <?php
505
+ $this->form->textbox($this->settings['Htax_category_template'], '6', false, __('The template for category breadcrumbs.', 'breadcrumb-navxt'));
506
+ $this->form->textbox($this->settings['Htax_category_template_no_anchor'], '4', false, __('The template for category breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
507
  ?>
508
  </table>
509
  <h2><?php _e('Tags', 'breadcrumb-navxt'); ?></h2>
510
  <table class="form-table">
511
  <?php
512
+ $this->form->textbox($this->settings['Htax_post_tag_template'], '6', false, __('The template for tag breadcrumbs.', 'breadcrumb-navxt'));
513
+ $this->form->textbox($this->settings['Htax_post_tag_template_no_anchor'], '4', false, __('The template for tag breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
514
  ?>
515
  </table>
516
  <h2><?php _e('Post Formats', 'breadcrumb-navxt'); ?></h2>
517
  <table class="form-table">
518
  <?php
519
+ $this->form->textbox($this->settings['Htax_post_format_template'], '6', false, __('The template for post format breadcrumbs.', 'breadcrumb-navxt'));
520
+ $this->form->textbox($this->settings['Htax_post_format_template_no_anchor'], '4', false, __('The template for post_format breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
521
  ?>
522
  </table>
523
  <?php
537
  <h3><?php echo mb_convert_case($taxonomy->label, MB_CASE_TITLE, 'UTF-8'); ?></h3>
538
  <table class="form-table">
539
  <?php
540
+ $this->form->textbox($this->settings['Htax_' . $taxonomy->name . '_template'], '6', false, sprintf(__('The template for %s breadcrumbs.', 'breadcrumb-navxt'), $label_lc));
541
+ $this->form->textbox($this->settings['Htax_' . $taxonomy->name . '_template_no_anchor'], '4', false, sprintf(__('The template for %s breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'), $label_lc));
542
  ?>
543
  </table>
544
  <?php
545
  }
546
  }
547
+ do_action($this->unique_prefix . '_after_settings_tab_taxonomy', $this->settings); ?>
548
  </fieldset>
549
  <fieldset id="miscellaneous" class="bcn_options">
550
  <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>
551
  <h2><?php _e('Author Archives', 'breadcrumb-navxt'); ?></h2>
552
  <table class="form-table">
553
  <?php
554
+ $this->form->textbox($this->settings['Hauthor_template'], '6', false, __('The template for author breadcrumbs.', 'breadcrumb-navxt'));
555
+ $this->form->textbox($this->settings['Hauthor_template_no_anchor'], '4', false, __('The template for author breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
556
+ $this->form->input_select($this->settings['Eauthor_name'], $this->settings['Eauthor_name']->get_allowed_vals(), false, __('display_name uses the name specified in "Display name publicly as" under the user profile the others correspond to options in the user profile.', 'breadcrumb-navxt'));
557
+ $optid = form::get_valid_id('aauthor_root');
558
  ?>
559
  <tr valign="top">
560
  <th scope="row">
561
  <label for="<?php echo $optid;?>"><?php esc_html_e('Author Root Page', 'breadcrumb-navxt');?></label>
562
  </th>
563
  <td>
564
+ <?php wp_dropdown_pages(array('name' => $this->unique_prefix . '_options[aauthor_root]', 'id' => $optid, 'echo' => 1, 'show_option_none' => __( '&mdash; Select &mdash;' ), 'option_none_value' => '0', 'selected' => $this->settings['aauthor_root']->get_value()));?>
565
  </td>
566
  </tr>
567
  </table>
568
  <h2><?php _e('Miscellaneous', 'breadcrumb-navxt'); ?></h2>
569
  <table class="form-table">
570
  <?php
571
+ $this->form->textbox($this->settings['Hdate_template'], '6', false, __('The template for date breadcrumbs.', 'breadcrumb-navxt'));
572
+ $this->form->textbox($this->settings['Hdate_template_no_anchor'], '4', false, __('The template for date breadcrumbs, used only when the breadcrumb is not linked.', 'breadcrumb-navxt'));
573
+ $this->form->textbox($this->settings['Hsearch_template'], '6', false, __('The anchor template for search breadcrumbs, used only when the search results span several pages.', 'breadcrumb-navxt'));
574
+ $this->form->textbox($this->settings['Hsearch_template_no_anchor'], '4', false, __('The anchor template for search breadcrumbs, used only when the search results span several pages and the breadcrumb is not linked.', 'breadcrumb-navxt'));
575
+ $this->form->input_text($this->settings['S404_title'], 'regular-text');
576
+ $this->form->textbox($this->settings['H404_template'], '4', false, __('The template for 404 breadcrumbs.', 'breadcrumb-navxt'));
577
  ?>
578
  </table>
579
  <h2><?php _e('Deprecated', 'breadcrumb-navxt'); ?></h2>
584
  </th>
585
  <td>
586
  <label>
587
+ <input name="bcn_options[blimit_title]" type="checkbox" id="blimit_title" value="true" <?php checked(true, $this->settings['blimit_title']->get_value()); ?> />
588
  <?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>');?>
589
  </label><br />
590
  <ul>
591
  <li>
592
  <label for="amax_title_length">
593
  <?php esc_html_e('Max Title Length: ','breadcrumb-navxt');?>
594
+ <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" />
595
  </label>
596
  </li>
597
  </ul>
598
  </td>
599
  </tr>
600
  </table>
601
+ <?php do_action($this->unique_prefix . '_after_settings_tab_miscellaneous', $this->settings); ?>
602
  </fieldset>
603
+ <?php do_action($this->unique_prefix . '_after_settings_tabs', $this->settings); ?>
604
  </div>
605
  <p class="submit"><input type="submit" class="button-primary" name="bcn_admin_options" value="<?php esc_attr_e('Save Changes') ?>" /></p>
606
  </form>
class.bcn_breadcrumb.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2007-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ require_once(dirname(__FILE__) . '/includes/block_direct_access.php');
21
  class bcn_breadcrumb
22
  {
23
  //Our member variables
24
- const version = '6.6.0';
25
  //The main text that will be shown
26
  protected $title;
27
  //The breadcrumb's template, used durring assembly
@@ -37,7 +37,6 @@ class bcn_breadcrumb
37
  private $_title = null;
38
  //The type of this breadcrumb
39
  protected $type;
40
- protected $allowed_html = array();
41
  const default_template_no_anchor = '<span property="itemListElement" typeof="ListItem"><span property="name" class="%type%">%htitle%</span><meta property="url" content="%link%"><meta property="position" content="%position%"></span>';
42
  /**
43
  * The enhanced default constructor, ends up setting all parameters via the set_ functions
@@ -50,8 +49,6 @@ class bcn_breadcrumb
50
  */
51
  public function __construct($title = '', $template = '', array $type = array(), $url = '', $id = null, $linked = false)
52
  {
53
- //Filter allowed_html array to allow others to add acceptable tags
54
- $this->allowed_html = apply_filters('bcn_allowed_html', wp_kses_allowed_html('post'));
55
  //The breadcrumb type
56
  $this->type = $type;
57
  //Set the resource id
@@ -74,7 +71,7 @@ class bcn_breadcrumb
74
  }
75
  else
76
  {
77
- $this->template_no_anchor = wp_kses(apply_filters('bcn_breadcrumb_template_no_anchor', $template, $this->type, $this->id), $this->allowed_html);
78
  $this->set_template(bcn_breadcrumb::get_default_template());
79
  }
80
  }
@@ -115,7 +112,7 @@ class bcn_breadcrumb
115
  /**
116
  * Function to set the internal URL variable
117
  *
118
- * @param string $url the url to link to
119
  */
120
  public function set_url($url)
121
  {
@@ -123,7 +120,16 @@ class bcn_breadcrumb
123
  $this->url = apply_filters('bcn_breadcrumb_url', $url, $this->type, $this->id);
124
  }
125
  /**
126
- * Function to se tthe internal breadcrumb linked status
 
 
 
 
 
 
 
 
 
127
  *
128
  * @param bool $linked whether or not the breadcrumb uses the linked or unlinked template
129
  */
@@ -131,6 +137,25 @@ class bcn_breadcrumb
131
  {
132
  $this->linked = apply_filters('bcn_breadcrumb_linked', $linked, $this->type, $this->id);
133
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  /**
135
  * Function to set the internal breadcrumb template
136
  *
@@ -139,7 +164,7 @@ class bcn_breadcrumb
139
  public function set_template($template)
140
  {
141
  //Assign the breadcrumb template
142
- $this->template = wp_kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id), $this->allowed_html);
143
  }
144
  /**
145
  * Function to set the internal breadcrumb ID
1
  <?php
2
  /*
3
+ Copyright 2007-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
21
  class bcn_breadcrumb
22
  {
23
  //Our member variables
24
+ const version = '7.0.0';
25
  //The main text that will be shown
26
  protected $title;
27
  //The breadcrumb's template, used durring assembly
37
  private $_title = null;
38
  //The type of this breadcrumb
39
  protected $type;
 
40
  const default_template_no_anchor = '<span property="itemListElement" typeof="ListItem"><span property="name" class="%type%">%htitle%</span><meta property="url" content="%link%"><meta property="position" content="%position%"></span>';
41
  /**
42
  * The enhanced default constructor, ends up setting all parameters via the set_ functions
49
  */
50
  public function __construct($title = '', $template = '', array $type = array(), $url = '', $id = null, $linked = false)
51
  {
 
 
52
  //The breadcrumb type
53
  $this->type = $type;
54
  //Set the resource id
71
  }
72
  else
73
  {
74
+ $this->template_no_anchor = $this->run_template_kses(apply_filters('bcn_breadcrumb_template_no_anchor', $template, $this->type, $this->id));
75
  $this->set_template(bcn_breadcrumb::get_default_template());
76
  }
77
  }
112
  /**
113
  * Function to set the internal URL variable
114
  *
115
+ * @param string $url the URL to link to
116
  */
117
  public function set_url($url)
118
  {
120
  $this->url = apply_filters('bcn_breadcrumb_url', $url, $this->type, $this->id);
121
  }
122
  /**
123
+ * Function to get the internal URL variable
124
+ *
125
+ * @return string the URL that the breadcrumb links to
126
+ */
127
+ public function get_url()
128
+ {
129
+ return $this->url;
130
+ }
131
+ /**
132
+ * Function to set the internal breadcrumb linked status
133
  *
134
  * @param bool $linked whether or not the breadcrumb uses the linked or unlinked template
135
  */
137
  {
138
  $this->linked = apply_filters('bcn_breadcrumb_linked', $linked, $this->type, $this->id);
139
  }
140
+ /**
141
+ * Function to check if this breadcrumb will be linked
142
+ *
143
+ * @return boolean whether or not this breadcrumb is linked
144
+ */
145
+ public function is_linked()
146
+ {
147
+ return $this->linked;
148
+ }
149
+ /**
150
+ * A wrapper for wp_kses which handles getting the allowed html
151
+ *
152
+ * @param string $template_str The tempalte string to run through kses
153
+ * @return string The template string post cleaning
154
+ */
155
+ protected function run_template_kses($template_str)
156
+ {
157
+ return wp_kses($template_str, apply_filters('bcn_allowed_html', wp_kses_allowed_html('post')));
158
+ }
159
  /**
160
  * Function to set the internal breadcrumb template
161
  *
164
  public function set_template($template)
165
  {
166
  //Assign the breadcrumb template
167
+ $this->template = $this->run_template_kses(apply_filters('bcn_breadcrumb_template', $template, $this->type, $this->id));
168
  }
169
  /**
170
  * Function to set the internal breadcrumb ID
class.bcn_breadcrumb_trail.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2015-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ require_once(dirname(__FILE__) . '/includes/block_direct_access.php');
21
  class bcn_breadcrumb_trail
22
  {
23
  //Our member variables
24
- const version = '6.6.0';
25
  //An array of breadcrumbs
26
  public $breadcrumbs = array();
27
  public $trail = array();
@@ -55,6 +55,9 @@ class bcn_breadcrumb_trail
55
  //Separator that is placed between each item in the breadcrumb trial, but not placed before
56
  //the first and not after the last breadcrumb
57
  'hseparator' => ' &gt; ',
 
 
 
58
  //Whether or not we should trim the breadcrumb titles
59
  'blimit_title' => false,
60
  //The maximum title length
@@ -67,7 +70,7 @@ class bcn_breadcrumb_trail
67
  //Should the post parent be followed first for this type, then fallback to the hierarchy type
68
  'bpost_page_hierarchy_parent_first' => false,
69
  //What hierarchy should be shown leading to the page
70
- 'Spost_page_hierarchy_type' => 'BCN_POST_PARENT',
71
  //The anchor template for page breadcrumbs
72
  'Hpost_page_template' => bcn_breadcrumb::get_default_template(),
73
  //The anchor template for page breadcrumbs, used when an anchor is not needed
@@ -93,7 +96,7 @@ class bcn_breadcrumb_trail
93
  //Should the trail reflect the referer taxonomy or not
94
  'bpost_post_taxonomy_referer' => false,
95
  //What hierarchy should be shown leading to the post, tag or category
96
- 'Spost_post_hierarchy_type' => 'category',
97
  //Attachment settings
98
  'bpost_attachment_archive_display' => false,
99
  'bpost_attachment_hierarchy_display' => true,
@@ -102,7 +105,7 @@ class bcn_breadcrumb_trail
102
  //Should the trail reflect the referer taxonomy or not
103
  'bpost_attachment_taxonomy_referer' => false,
104
  //What hierarchy should be shown leading to the attachment
105
- 'Spost_attachment_hierarchy_type' => 'BCN_POST_PARENT',
106
  //Give an invlaid page ID for the attachement root
107
  'apost_attachment_root' => 0,
108
  //The breadcrumb template for attachment breadcrumbs
@@ -141,7 +144,7 @@ class bcn_breadcrumb_trail
141
  'Hauthor_template_no_anchor' => sprintf('<span class="%%type%%">%1$s</span>',
142
  sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')),
143
  //Which of the various WordPress display types should the author breadcrumb display
144
- 'Sauthor_name' => 'display_name',
145
  //Give an invlaid page ID for the author root
146
  'aauthor_root' => 0,
147
  //Category stuff
@@ -205,11 +208,11 @@ class bcn_breadcrumb_trail
205
  //Setup array of valid author_name values
206
  $valid_author_name = array('display_name', 'nickname', 'first_name', 'last_name');
207
  //Make sure user picks only safe values
208
- if(in_array($this->opt['Sauthor_name'], $valid_author_name))
209
  {
210
  //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
211
  $breadcrumb = $this->add(new bcn_breadcrumb(
212
- get_the_author_meta($this->opt['Sauthor_name'], $author_data->ID),
213
  $this->opt['Hauthor_template_no_anchor'],
214
  array('author', 'current-item'),
215
  get_author_posts_url($author_data->ID),
@@ -328,7 +331,7 @@ class bcn_breadcrumb_trail
328
  if($this->opt['bpost_' . $type . '_hierarchy_display'])
329
  {
330
  //Check if we have a date 'taxonomy' request
331
- if($this->opt['Spost_' . $type . '_hierarchy_type'] === 'BCN_DATE')
332
  {
333
  $post = get_post($id);
334
  $this->do_day($post, $type, false, false);
@@ -336,7 +339,7 @@ class bcn_breadcrumb_trail
336
  $this->do_year($post, $type, false, false);
337
  }
338
  //Handle the use of hierarchical posts as the 'taxonomy'
339
- else if($this->opt['Spost_' . $type . '_hierarchy_type'] === 'BCN_POST_PARENT')
340
  {
341
  if($parent == null)
342
  {
@@ -355,7 +358,7 @@ class bcn_breadcrumb_trail
355
  }
356
  else
357
  {
358
- $taxonomy = $this->opt['Spost_' . $type . '_hierarchy_type'];
359
  //Possibly let the referer influence the taxonomy used
360
  if($this->opt['bpost_' . $type . '_taxonomy_referer'] && $referrer_taxonomy = $this->determine_taxonomy())
361
  {
@@ -375,8 +378,7 @@ class bcn_breadcrumb_trail
375
  if($term instanceof WP_Term)
376
  {
377
  //Fill out the term hiearchy
378
- //FIXME: Change to just passing in term instance (work for 7.0)
379
- $parent = $this->term_parents($term->term_id, $term->taxonomy);
380
  }
381
  }
382
  //Handle the rest of the taxonomies, including tags
@@ -392,7 +394,7 @@ class bcn_breadcrumb_trail
392
  $parent = get_post($id);
393
  }
394
  //Finish off with trying to find the type archive
395
- $this->type_archive($parent, $parent->post_type);
396
  }
397
  /**
398
  * A Breadcrumb Trail Filling Function
@@ -414,8 +416,7 @@ class bcn_breadcrumb_trail
414
  //For single terms, treat as if they are hierarchical
415
  if(count($bcn_terms) === 1 && $bcn_terms[0] instanceof WP_Term)
416
  {
417
- //FIXME: Change to just passing in term instance (work for 7.0)
418
- return $this->term_parents($bcn_terms[0]->term_id, $bcn_terms[0]->taxonomy);
419
  }
420
  $title = '';
421
  $is_first = true;
@@ -443,30 +444,27 @@ class bcn_breadcrumb_trail
443
  *
444
  * This recursive functions fills the trail with breadcrumbs for parent terms
445
  *
446
- * @param int $id The id of the term
447
- * @param string $taxonomy The name of the taxonomy that the term belongs to
448
  *
449
  * @return WP_Term|WP_Error The term we stopped at
450
  */
451
- protected function term_parents($id, $taxonomy)
452
  {
453
- //Get the current category object, filter applied within this call
454
- $term = get_term($id, $taxonomy);
455
  if($term instanceof WP_Term)
456
  {
457
  //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
458
  $breadcrumb = $this->add(new bcn_breadcrumb(
459
  $term->name, $this->opt['Htax_' . $term->taxonomy . '_template'],
460
  array('taxonomy', $term->taxonomy),
461
- $this->maybe_add_post_type_arg(get_term_link($term), null, $term->taxonomy),
462
  $term->term_id,
463
  true));
464
  //Make sure the id is valid, and that we won't end up spinning in a loop
465
- if($term->parent && $term->parent != $id)
466
  {
467
  //Figure out the rest of the term hiearchy via recursion
468
- //FIXME: Change to just passing in term instance (work for 7.0)
469
- $ret_term = $this->term_parents($term->parent, $taxonomy);
470
  //May end up with WP_Error, don't update the term if that's the case
471
  if($ret_term instanceof WP_Term)
472
  {
@@ -595,8 +593,7 @@ class bcn_breadcrumb_trail
595
  //Get parents of current term
596
  if($term->parent)
597
  {
598
- //FIXME: Change to just passing in term instance (work for 7.0)
599
- $this->term_parents($term->parent, $term->taxonomy);
600
  }
601
  }
602
  /**
@@ -694,32 +691,6 @@ class bcn_breadcrumb_trail
694
  $breadcrumb->set_linked(true);
695
  }
696
  }
697
- /**
698
- * A Breadcrumb Trail Filling Function
699
- *
700
- * This functions fills a breadcrumb for a post type archive (WP 3.1 feature)
701
- *
702
- * @param string type_str The name of the CPT to generate the archive breadcrumb for
703
- * @param bool $is_paged Whether or not the current resource is on a page other than page 1
704
- */
705
- protected function do_archive_by_post_type($type_str, $is_paged = false)
706
- {
707
- //Manually grabbing the post type object insted of post_type_archive_title('', false) to remove get_query_var() dependancy
708
- $post_type_obj = get_post_type_object($type_str);
709
- $title = apply_filters('post_type_archive_title', $post_type_obj->labels->name, $type_str);
710
- //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
711
- $breadcrumb = $this->add(new bcn_breadcrumb(
712
- $title,
713
- $this->opt['Hpost_' . $type_str . '_template_no_anchor'],
714
- array('archive', 'post-' . $type_str . '-archive', 'current-item'),
715
- get_post_type_archive_link($type_str)));
716
- if($this->opt['bcurrent_item_linked'] || ($is_paged && $this->opt['bpaged_display']))
717
- {
718
-
719
- $breadcrumb->set_template($this->opt['Hpost_' . $type_str . '_template']);
720
- $breadcrumb->set_linked(true);
721
- }
722
- }
723
  /**
724
  * A Breadcrumb Trail Filling Function
725
  *
@@ -880,6 +851,51 @@ class bcn_breadcrumb_trail
880
  }
881
  return $url;
882
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
883
  /**
884
  * A Breadcrumb Trail Filling Function
885
  *
@@ -887,46 +903,23 @@ class bcn_breadcrumb_trail
887
  *
888
  * @param WP_Post|WP_Taxonomy $type The post or taxonomy to generate the archive breadcrumb for
889
  * @param string $type_str The type string for the archive
890
- *
891
- * TODO: Split and redo calls to it, see #224
892
  */
893
  protected function type_archive($type, $type_str = false)
894
  {
895
- global $wp_taxonomies;
896
  if(!isset($type->taxonomy) && $type_str === false) //TODO could probably check the class type here
897
  {
898
  $type_str = $this->get_type_string_query_var();
899
  }
900
- //If this is a custom post type with a post type archive, add it
901
- if($type_str && !$this->is_builtin($type_str) && $this->opt['bpost_' . $type_str . '_archive_display'] && $this->has_archive($type_str))
 
 
902
  {
903
- //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
904
- $breadcrumb = $this->add(new bcn_breadcrumb(
905
- $this->post_type_archive_title(get_post_type_object($type_str)),
906
- $this->opt['Hpost_' . $type_str . '_template'],
907
- array('post', 'post-' . $type_str . '-archive'),
908
- get_post_type_archive_link($type_str),
909
- null,
910
- true));
911
- }
912
- //Otherwise, if this is a custom taxonomy with an archive, add it
913
- else if(isset($type->taxonomy) && isset($wp_taxonomies[$type->taxonomy]->object_type[0])
914
- && !$this->is_builtin($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]))
915
- && $this->opt['bpost_' . $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]) . '_archive_display']
916
- && $this->has_archive($this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]))
917
- && !$this->is_type_query_var_array() && apply_filters('bcn_show_type_term_archive', true, $type->taxonomy))
918
- {
919
- //We end up using the post type in several places, give it a variable
920
- $post_type = apply_filters('bcn_type_archive_post_type', $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]));
921
- //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
922
- $breadcrumb = $this->add(new bcn_breadcrumb(
923
- $this->post_type_archive_title(get_post_type_object($post_type)),
924
- $this->opt['Hpost_' . $post_type . '_template'],
925
- array('post', 'post-' . $post_type . '-archive'),
926
- get_post_type_archive_link($post_type),
927
- null,
928
- true));
929
  }
 
 
930
  }
931
  /**
932
  * A Breadcrumb Trail Filling Function
@@ -1086,32 +1079,31 @@ class bcn_breadcrumb_trail
1086
  //For date based archives
1087
  if(is_date())
1088
  {
 
1089
  //First deal with the day breadcrumb
1090
  if(is_day())
1091
  {
1092
- $this->do_day(get_post(), $this->get_type_string_query_var(), is_paged(), true);
1093
  }
1094
  //Now deal with the month breadcrumb
1095
  if(is_month() || is_day())
1096
  {
1097
- $this->do_month(get_post(), $this->get_type_string_query_var(), is_paged(), is_month());
1098
  }
1099
- $this->do_year(get_post(), $this->get_type_string_query_var(), is_paged(), is_year());
1100
- $type_str = $this->get_type_string_query_var();
1101
- $this->type_archive($type, $type_str);
1102
  }
1103
  //If we have a post type archive, and it does not have a root page generate the archive
1104
  else if(is_post_type_archive() && !isset($type->taxonomy)
1105
  && (!is_numeric($this->opt['apost_' . $type_str . '_root']) || $this->opt['bpost_' . $type_str . '_archive_display']))
1106
  {
1107
- $this->do_archive_by_post_type($this->get_type_string_query_var(), is_paged());
1108
  }
1109
  //For taxonomy based archives
1110
  else if(is_category() || is_tag() || is_tax())
1111
  {
1112
  $this->do_archive_by_term($type, is_paged());
1113
- $this->type_archive($type);
1114
- $type_str = $this->get_type_string_query_var($GLOBALS['wp_taxonomies'][$type->taxonomy]->object_type[0]);
1115
  }
1116
  else
1117
  {
@@ -1134,8 +1126,7 @@ class bcn_breadcrumb_trail
1134
  if(isset($type->taxonomy))
1135
  {
1136
  $this->do_archive_by_term($type, is_paged());
1137
- $this->type_archive($type);
1138
- $type_str = $this->get_type_string_query_var($wp_taxonomies[$type->taxonomy]->object_type[0]);
1139
  }
1140
  //Otherwise, it's likely the blog page
1141
  else if($this->opt['bblog_display'] || is_home())
@@ -1164,21 +1155,20 @@ class bcn_breadcrumb_trail
1164
  //Handle Posts
1165
  if($item instanceof WP_Post)
1166
  {
1167
- $this->do_post($item, false, true);
1168
  $this->do_root($item->post_type, $this->opt['apost_' . $item->post_type . '_root'], false, false);
1169
  }
1170
  //Handle Terms
1171
  else if($item instanceof WP_Term)
1172
  {
1173
- $this->do_archive_by_term($item, true);
1174
- $this->type_archive($item);
1175
- $type_str = $this->get_type_string_query_var($GLOBALS['wp_taxonomies'][$item->taxonomy]->object_type[0]);
1176
  $this->do_root($type_str, $this->opt['apost_' . $type_str . '_root'], is_paged(), $this->treat_as_root_page($type_str));
1177
  }
1178
  //Handle Author Archives
1179
  else if($item instanceof WP_User)
1180
  {
1181
- $this->do_author($item, true);
1182
  $this->do_root('post', $this->opt['aauthor_root'], false, false);
1183
  }
1184
  $this->do_home(true, false, false);
@@ -1208,67 +1198,81 @@ class bcn_breadcrumb_trail
1208
  * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
1209
  * @param bool $reverse[optional] Whether to reverse the output or not.
1210
  * @param string $template The template to use for the string output.
 
1211
  *
1212
  * @return void Void if Option to print out breadcrumb trail was chosen.
1213
  * @return string String-Data of breadcrumb trail.
1214
  */
1215
- public function display($linked = true, $reverse = false, $template = '%1$s%2$s')
1216
  {
1217
  //Set trail order based on reverse flag
1218
  $this->order($reverse);
1219
  //The main compiling loop
1220
- $trail_str = $this->display_loop($linked, $reverse, $template);
1221
  return $trail_str;
1222
  }
1223
  /**
1224
  * This function assembles the breadcrumbs in the breadcrumb trail in accordance with the passed in template
1225
  *
 
1226
  * @param bool $linked Whether to allow hyperlinks in the trail or not.
1227
  * @param bool $reverse Whether to reverse the output or not.
1228
- * @param string $template The template to use for the string output.
 
 
1229
  *
1230
- * @return string String-Data of breadcrumb trail.
1231
  */
1232
- protected function display_loop($linked, $reverse, $template)
1233
  {
1234
  $position = 1;
1235
- $last_position = count($this->breadcrumbs);
 
 
 
 
1236
  //Initilize the string which will hold the assembled trail
1237
  $trail_str = '';
1238
- foreach($this->breadcrumbs as $key => $breadcrumb)
1239
- {
1240
- $types = $breadcrumb->get_types();
1241
- array_walk($types, 'sanitize_html_class');
1242
- $attrib_array = array('class' => $types);
1243
- $attribs = '';
1244
- //Deal with the separator
1245
- if($position < $last_position)
1246
  {
1247
- $separator = $this->opt['hseparator'];
1248
  }
1249
- else
1250
  {
1251
- $separator = '';
 
1252
  }
1253
- //Allow others to hook into the attribute array
1254
- $attrib_array= apply_filters('bcn_display_attribute_array', $attrib_array, $breadcrumb->get_types(), $breadcrumb->get_id());
1255
- //Stringify the array
1256
- foreach($attrib_array as $attrib => $value)
1257
  {
1258
- $attribs .= sprintf(' %1$s="%2$s"', esc_attr($attrib), esc_attr(implode(' ', $value)));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1259
  }
1260
- //Filter li_attributes adding attributes to the li element
1261
- $attribs = apply_filters_deprecated('bcn_li_attributes', array($attribs, $breadcrumb->get_types(), $breadcrumb->get_id()), '6.0.0', 'bcn_display_attributes');
1262
- $attribs = apply_filters('bcn_display_attributes', $attribs, $breadcrumb->get_types(), $breadcrumb->get_id());
1263
- //Trim titles, if requested
1264
- if($this->opt['blimit_title'] && $this->opt['amax_title_length'] > 0)
1265
  {
1266
- //Trim the breadcrumb's title
1267
- $breadcrumb->title_trim($this->opt['amax_title_length']);
 
 
 
1268
  }
1269
- //Assemble the breadcrumb
1270
- $trail_str .= sprintf($template, $breadcrumb->assemble($linked, $position, ($key === 0)), $separator, $attribs);
1271
- $position++;
1272
  }
1273
  return $trail_str;
1274
  }
@@ -1287,23 +1291,35 @@ class bcn_breadcrumb_trail
1287
  $trail_str = (object)array(
1288
  '@context' => 'http://schema.org',
1289
  '@type' => 'BreadcrumbList',
1290
- 'itemListElement' => $this->json_ld_loop());
1291
  return $trail_str;
1292
  }
1293
  /**
1294
  * This function assembles all of the breadcrumbs into an object ready for json_encode
1295
  *
 
1296
  * @return array The array of breadcrumbs prepared for JSON-LD
1297
  */
1298
- protected function json_ld_loop()
1299
  {
1300
- $postion = 1;
 
 
 
 
1301
  $breadcrumbs = array();
1302
  //Loop around our breadcrumbs, call the JSON-LD assembler
1303
  foreach($this->breadcrumbs as $breadcrumb)
1304
  {
1305
- $breadcrumbs[] = $breadcrumb->assemble_json_ld($postion);
1306
- $postion++;
 
 
 
 
 
 
 
1307
  }
1308
  return $breadcrumbs;
1309
  }
1
  <?php
2
  /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
21
  class bcn_breadcrumb_trail
22
  {
23
  //Our member variables
24
+ const version = '7.0.0';
25
  //An array of breadcrumbs
26
  public $breadcrumbs = array();
27
  public $trail = array();
55
  //Separator that is placed between each item in the breadcrumb trial, but not placed before
56
  //the first and not after the last breadcrumb
57
  'hseparator' => ' &gt; ',
58
+ //Separator that is placed between each item in the breadcrumb trial on the 2nd and higher dimensions, but not placed before
59
+ //the first and not after the last breadcrumb
60
+ 'hseparator_higher_dim' => ', ',
61
  //Whether or not we should trim the breadcrumb titles
62
  'blimit_title' => false,
63
  //The maximum title length
70
  //Should the post parent be followed first for this type, then fallback to the hierarchy type
71
  'bpost_page_hierarchy_parent_first' => false,
72
  //What hierarchy should be shown leading to the page
73
+ 'Epost_page_hierarchy_type' => 'BCN_POST_PARENT',
74
  //The anchor template for page breadcrumbs
75
  'Hpost_page_template' => bcn_breadcrumb::get_default_template(),
76
  //The anchor template for page breadcrumbs, used when an anchor is not needed
96
  //Should the trail reflect the referer taxonomy or not
97
  'bpost_post_taxonomy_referer' => false,
98
  //What hierarchy should be shown leading to the post, tag or category
99
+ 'Epost_post_hierarchy_type' => 'category',
100
  //Attachment settings
101
  'bpost_attachment_archive_display' => false,
102
  'bpost_attachment_hierarchy_display' => true,
105
  //Should the trail reflect the referer taxonomy or not
106
  'bpost_attachment_taxonomy_referer' => false,
107
  //What hierarchy should be shown leading to the attachment
108
+ 'Epost_attachment_hierarchy_type' => 'BCN_POST_PARENT',
109
  //Give an invlaid page ID for the attachement root
110
  'apost_attachment_root' => 0,
111
  //The breadcrumb template for attachment breadcrumbs
144
  'Hauthor_template_no_anchor' => sprintf('<span class="%%type%%">%1$s</span>',
145
  sprintf(esc_attr__('Articles by: %1$s', 'breadcrumb-navxt'), '%htitle%')),
146
  //Which of the various WordPress display types should the author breadcrumb display
147
+ 'Eauthor_name' => 'display_name',
148
  //Give an invlaid page ID for the author root
149
  'aauthor_root' => 0,
150
  //Category stuff
208
  //Setup array of valid author_name values
209
  $valid_author_name = array('display_name', 'nickname', 'first_name', 'last_name');
210
  //Make sure user picks only safe values
211
+ if(in_array($this->opt['Eauthor_name'], $valid_author_name))
212
  {
213
  //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
214
  $breadcrumb = $this->add(new bcn_breadcrumb(
215
+ get_the_author_meta($this->opt['Eauthor_name'], $author_data->ID),
216
  $this->opt['Hauthor_template_no_anchor'],
217
  array('author', 'current-item'),
218
  get_author_posts_url($author_data->ID),
331
  if($this->opt['bpost_' . $type . '_hierarchy_display'])
332
  {
333
  //Check if we have a date 'taxonomy' request
334
+ if($this->opt['Epost_' . $type . '_hierarchy_type'] === 'BCN_DATE')
335
  {
336
  $post = get_post($id);
337
  $this->do_day($post, $type, false, false);
339
  $this->do_year($post, $type, false, false);
340
  }
341
  //Handle the use of hierarchical posts as the 'taxonomy'
342
+ else if($this->opt['Epost_' . $type . '_hierarchy_type'] === 'BCN_POST_PARENT')
343
  {
344
  if($parent == null)
345
  {
358
  }
359
  else
360
  {
361
+ $taxonomy = $this->opt['Epost_' . $type . '_hierarchy_type'];
362
  //Possibly let the referer influence the taxonomy used
363
  if($this->opt['bpost_' . $type . '_taxonomy_referer'] && $referrer_taxonomy = $this->determine_taxonomy())
364
  {
378
  if($term instanceof WP_Term)
379
  {
380
  //Fill out the term hiearchy
381
+ $parent = $this->term_parents($term, $type);
 
382
  }
383
  }
384
  //Handle the rest of the taxonomies, including tags
394
  $parent = get_post($id);
395
  }
396
  //Finish off with trying to find the type archive
397
+ $this->maybe_do_archive_by_post_type($parent->post_type);
398
  }
399
  /**
400
  * A Breadcrumb Trail Filling Function
416
  //For single terms, treat as if they are hierarchical
417
  if(count($bcn_terms) === 1 && $bcn_terms[0] instanceof WP_Term)
418
  {
419
+ return $this->term_parents($bcn_terms[0], get_post_type($id));
 
420
  }
421
  $title = '';
422
  $is_first = true;
444
  *
445
  * This recursive functions fills the trail with breadcrumbs for parent terms
446
  *
447
+ * @param WP_Term $term The term object to generate breadcrumbs for
448
+ * @param string|null $type The post type string to use for determining whether or not to add the post type argument
449
  *
450
  * @return WP_Term|WP_Error The term we stopped at
451
  */
452
+ protected function term_parents($term, $type = null)
453
  {
 
 
454
  if($term instanceof WP_Term)
455
  {
456
  //Place the breadcrumb in the trail, uses the constructor to set the title, template, and type, get a pointer to it in return
457
  $breadcrumb = $this->add(new bcn_breadcrumb(
458
  $term->name, $this->opt['Htax_' . $term->taxonomy . '_template'],
459
  array('taxonomy', $term->taxonomy),
460
+ $this->maybe_add_post_type_arg(get_term_link($term), $type, $term->taxonomy),
461
  $term->term_id,
462
  true));
463
  //Make sure the id is valid, and that we won't end up spinning in a loop
464
+ if($term->parent && $term->parent != $term->term_id)
465
  {
466
  //Figure out the rest of the term hiearchy via recursion
467
+ $ret_term = $this->term_parents(get_term($term->parent, $term->taxonomy), $type);
 
468
  //May end up with WP_Error, don't update the term if that's the case
469
  if($ret_term instanceof WP_Term)
470
  {
593
  //Get parents of current term
594
  if($term->parent)
595
  {
596
+ $this->term_parents(get_term($term->parent, $term->taxonomy));
 
597
  }
598
  }
599
  /**
691
  $breadcrumb->set_linked(true);
692
  }
693
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
694
  /**
695
  * A Breadcrumb Trail Filling Function
696
  *
851
  }
852
  return $url;
853
  }
854
+ /**
855
+ * A Breadcrumb Trail Filling Function
856
+ *
857
+ * This functions fills a breadcrumb for a post type archive (WP 3.1 feature)
858
+ *
859
+ * @param string type_str The name of the CPT to generate the archive breadcrumb for
860
+ * @param bool $force_link Whether or not to force this breadcrumb to be linked
861
+ * @param bool $is_paged Whether or not the current resource is on a page other than page 1
862
+ * @param bool $is_current_item Whether or not the breadcrumb being generated is the current item
863
+ */
864
+ protected function do_archive_by_post_type($type_str, $force_link = false, $is_paged = false, $is_current_item = true)
865
+ {
866
+ //Place the breadcrumb in the trail, uses the constructor to set the title, prefix, and suffix, get a pointer to it in return
867
+ $breadcrumb = $this->add(new bcn_breadcrumb(
868
+ $this->post_type_archive_title(get_post_type_object($type_str)),
869
+ $this->opt['Hpost_' . $type_str . '_template_no_anchor'],
870
+ array('archive', 'post-' . $type_str . '-archive'),
871
+ get_post_type_archive_link($type_str)));
872
+ if($is_current_item)
873
+ {
874
+ $breadcrumb->add_type('current-item');
875
+ }
876
+ //Under a couple of circumstances we will want to link this breadcrumb
877
+ if($force_link || ($is_current_item && $this->opt['bcurrent_item_linked']) || ($is_paged && $this->opt['bpaged_display']))
878
+ {
879
+ //Change the template over to the normal, linked one
880
+ $breadcrumb->set_template($this->opt['Hpost_' . $type_str. '_template']);
881
+ //Add the link
882
+ $breadcrumb->set_linked(true);
883
+ }
884
+ }
885
+ /**
886
+ * A wrapper function for do_archive_by_post_type which checks to ensure generating the post type archive is appropriate
887
+ *
888
+ * @param string $type_str The type string for the post type archive
889
+ */
890
+ protected function maybe_do_archive_by_post_type($type_str)
891
+ {
892
+ //If this is a custom post type with a post type archive, add it
893
+ if(!$this->is_builtin($type_str) && $this->opt['bpost_' . $type_str . '_archive_display'] && $this->has_archive($type_str))
894
+ {
895
+ //Going farther down the rabbit hole here
896
+ $this->do_archive_by_post_type($type_str, true, false, false);
897
+ }
898
+ }
899
  /**
900
  * A Breadcrumb Trail Filling Function
901
  *
903
  *
904
  * @param WP_Post|WP_Taxonomy $type The post or taxonomy to generate the archive breadcrumb for
905
  * @param string $type_str The type string for the archive
 
 
906
  */
907
  protected function type_archive($type, $type_str = false)
908
  {
909
+ //Not at taxonomy, and didn't get a type string, see if we can get the info from the query var
910
  if(!isset($type->taxonomy) && $type_str === false) //TODO could probably check the class type here
911
  {
912
  $type_str = $this->get_type_string_query_var();
913
  }
914
+ //Have a taxonomy, try to figure the type out from that
915
+ else if(isset($type->taxonomy) && isset($GLOBALS['wp_taxonomies'][$type->taxonomy]->object_type[0])
916
+ && !$this->is_type_query_var_array()
917
+ && apply_filters('bcn_show_type_term_archive', true, $type->taxonomy))
918
  {
919
+ $type_str = apply_filters('bcn_type_archive_post_type', $this->get_type_string_query_var($GLOBALS['wp_taxonomies'][$type->taxonomy]->object_type[0]));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
920
  }
921
+ $this->maybe_do_archive_by_post_type($type_str);
922
+ return $type_str;
923
  }
924
  /**
925
  * A Breadcrumb Trail Filling Function
1079
  //For date based archives
1080
  if(is_date())
1081
  {
1082
+ $type_str = $this->get_type_string_query_var();
1083
  //First deal with the day breadcrumb
1084
  if(is_day())
1085
  {
1086
+ $this->do_day(get_post(), $type_str, is_paged(), true);
1087
  }
1088
  //Now deal with the month breadcrumb
1089
  if(is_month() || is_day())
1090
  {
1091
+ $this->do_month(get_post(), $type_str, is_paged(), is_month());
1092
  }
1093
+ $this->do_year(get_post(), $type_str, is_paged(), is_year());
1094
+ $this->maybe_do_archive_by_post_type($type_str);
 
1095
  }
1096
  //If we have a post type archive, and it does not have a root page generate the archive
1097
  else if(is_post_type_archive() && !isset($type->taxonomy)
1098
  && (!is_numeric($this->opt['apost_' . $type_str . '_root']) || $this->opt['bpost_' . $type_str . '_archive_display']))
1099
  {
1100
+ $this->do_archive_by_post_type($this->get_type_string_query_var(), false, is_paged(), true);
1101
  }
1102
  //For taxonomy based archives
1103
  else if(is_category() || is_tag() || is_tax())
1104
  {
1105
  $this->do_archive_by_term($type, is_paged());
1106
+ $type_str = $this->type_archive($type);
 
1107
  }
1108
  else
1109
  {
1126
  if(isset($type->taxonomy))
1127
  {
1128
  $this->do_archive_by_term($type, is_paged());
1129
+ $type_str = $this->type_archive($type);
 
1130
  }
1131
  //Otherwise, it's likely the blog page
1132
  else if($this->opt['bblog_display'] || is_home())
1155
  //Handle Posts
1156
  if($item instanceof WP_Post)
1157
  {
1158
+ $this->do_post($item, false);
1159
  $this->do_root($item->post_type, $this->opt['apost_' . $item->post_type . '_root'], false, false);
1160
  }
1161
  //Handle Terms
1162
  else if($item instanceof WP_Term)
1163
  {
1164
+ $this->do_archive_by_term($item);
1165
+ $type_str = $this->type_archive($item);
 
1166
  $this->do_root($type_str, $this->opt['apost_' . $type_str . '_root'], is_paged(), $this->treat_as_root_page($type_str));
1167
  }
1168
  //Handle Author Archives
1169
  else if($item instanceof WP_User)
1170
  {
1171
+ $this->do_author($item);
1172
  $this->do_root('post', $this->opt['aauthor_root'], false, false);
1173
  }
1174
  $this->do_home(true, false, false);
1198
  * @param bool $linked[optional] Whether to allow hyperlinks in the trail or not.
1199
  * @param bool $reverse[optional] Whether to reverse the output or not.
1200
  * @param string $template The template to use for the string output.
1201
+ * @param string $outer_template The template to place an entire dimension of the trail into for all dimensions higher than 1.
1202
  *
1203
  * @return void Void if Option to print out breadcrumb trail was chosen.
1204
  * @return string String-Data of breadcrumb trail.
1205
  */
1206
+ public function display($linked = true, $reverse = false, $template = '%1$s%2$s', $outer_template = '<span>%1$s</span>%2$s')
1207
  {
1208
  //Set trail order based on reverse flag
1209
  $this->order($reverse);
1210
  //The main compiling loop
1211
+ $trail_str = $this->display_loop($this->breadcrumbs, $linked, $reverse, $template, $outer_template, $this->opt['hseparator']);
1212
  return $trail_str;
1213
  }
1214
  /**
1215
  * This function assembles the breadcrumbs in the breadcrumb trail in accordance with the passed in template
1216
  *
1217
+ * @param array $breadcrumbs Array containing bcn_breadcrumb objects to render
1218
  * @param bool $linked Whether to allow hyperlinks in the trail or not.
1219
  * @param bool $reverse Whether to reverse the output or not.
1220
+ * @param string $template The template to use for the string output of each breadcrumb. Also known as the inner template.
1221
+ * @param string $outer_template The template to place an entire dimension of the trail into for all dimensions higher than 1.
1222
+ * @param string $separator The separator to use at this level of the breadcrumb trail
1223
  *
1224
+ * @return string Compiled string version of breadcrumb trail ready for display.
1225
  */
1226
+ protected function display_loop($breadcrumbs, $linked, $reverse, $template, $outer_template, $separator)
1227
  {
1228
  $position = 1;
1229
+ $last_position = count($breadcrumbs);
1230
+ if($reverse)
1231
+ {
1232
+ $position = $last_position;
1233
+ }
1234
  //Initilize the string which will hold the assembled trail
1235
  $trail_str = '';
1236
+ foreach($breadcrumbs as $key => $breadcrumb)
1237
+ {
1238
+ //Blank the separator if we are dealing with what is the last breadcrumb in the assembled trail
1239
+ if((!$reverse && ($position >= $last_position)) || ($reverse && $position == 1))
 
 
 
 
1240
  {
1241
+ $separator = '';
1242
  }
1243
+ if(is_array($breadcrumb))
1244
  {
1245
+ $trail_str .= sprintf($outer_template,
1246
+ $this->display_loop($breadcrumb, $linked, $reverse, $template, $outer_template, $this->opt['hseparator_higher_dim']), $separator);
1247
  }
1248
+ else if($breadcrumb instanceof bcn_breadcrumb)
 
 
 
1249
  {
1250
+ $types = $breadcrumb->get_types();
1251
+ array_walk($types, 'sanitize_html_class');
1252
+ $attrib_array = array('class' => $types);
1253
+ $attribs = '';
1254
+ //Allow others to hook into the attribute array
1255
+ $attrib_array = apply_filters('bcn_display_attribute_array', $attrib_array, $breadcrumb->get_types(), $breadcrumb->get_id());
1256
+ //Stringify the array
1257
+ foreach($attrib_array as $attrib => $value)
1258
+ {
1259
+ $attribs .= sprintf(' %1$s="%2$s"', esc_attr($attrib), esc_attr(implode(' ', $value)));
1260
+ }
1261
+ //Filter li_attributes adding attributes to the li element
1262
+ //TODO: Remove the bcn_li_attributes filter
1263
+ $attribs = apply_filters_deprecated('bcn_li_attributes', array($attribs, $breadcrumb->get_types(), $breadcrumb->get_id()), '6.0.0', 'bcn_display_attributes');
1264
+ $attribs = apply_filters('bcn_display_attributes', $attribs, $breadcrumb->get_types(), $breadcrumb->get_id());
1265
+ //Assemble the breadcrumb
1266
+ $trail_str .= sprintf($template, $breadcrumb->assemble($linked, $position, ($key === 0)), $separator, $attribs);
1267
  }
1268
+ if($reverse)
 
 
 
 
1269
  {
1270
+ $position--;
1271
+ }
1272
+ else
1273
+ {
1274
+ $position++;
1275
  }
 
 
 
1276
  }
1277
  return $trail_str;
1278
  }
1291
  $trail_str = (object)array(
1292
  '@context' => 'http://schema.org',
1293
  '@type' => 'BreadcrumbList',
1294
+ 'itemListElement' => $this->json_ld_loop($reverse));
1295
  return $trail_str;
1296
  }
1297
  /**
1298
  * This function assembles all of the breadcrumbs into an object ready for json_encode
1299
  *
1300
+ * @param bool $reverse[optional] Whether to reverse the output or not.
1301
  * @return array The array of breadcrumbs prepared for JSON-LD
1302
  */
1303
+ protected function json_ld_loop($reverse = false)
1304
  {
1305
+ $position = 1;
1306
+ if($reverse)
1307
+ {
1308
+ $position = count($this->breadcrumbs);
1309
+ }
1310
  $breadcrumbs = array();
1311
  //Loop around our breadcrumbs, call the JSON-LD assembler
1312
  foreach($this->breadcrumbs as $breadcrumb)
1313
  {
1314
+ $breadcrumbs[] = $breadcrumb->assemble_json_ld($position);
1315
+ if($reverse)
1316
+ {
1317
+ $position--;
1318
+ }
1319
+ else
1320
+ {
1321
+ $position++;
1322
+ }
1323
  }
1324
  return $breadcrumbs;
1325
  }
class.bcn_network_admin.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2015-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -22,13 +22,14 @@ if(!class_exists('bcn_admin'))
22
  {
23
  require_once(dirname(__FILE__) . '/class.bcn_admin.php');
24
  }
 
25
  /**
26
  * The administrative interface class
27
  *
28
  */
29
  class bcn_network_admin extends bcn_admin
30
  {
31
- const version = '6.6.0';
32
  protected $full_name = 'Breadcrumb NavXT Network Settings';
33
  protected $access_level = 'manage_network_options';
34
  /**
@@ -36,10 +37,10 @@ class bcn_network_admin extends bcn_admin
36
  * @param bcn_breadcrumb_trail $breadcrumb_trail a breadcrumb trail object
37
  * @param string $basename The basename of the plugin
38
  */
39
- function __construct(bcn_breadcrumb_trail &$breadcrumb_trail, $basename)
40
  {
41
  //We're going to make sure we load the parent's constructor
42
- parent::__construct($breadcrumb_trail, $basename);
43
  //Change to the proper name
44
  $this->full_name = __('Breadcrumb NavXT Network Settings', 'breadcrumb-navxt');
45
  //Remove the hook added by the parent as we don't want this classes settings page everywhere
@@ -143,7 +144,7 @@ class bcn_network_admin extends bcn_admin
143
  {
144
  if(defined('BCN_SETTINGS_USE_LOCAL') && BCN_SETTINGS_USE_LOCAL)
145
  {
146
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Individual site settings will override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_isiteoveride');
147
  }
148
  else if(defined('BCN_SETTINGS_USE_NETWORK') && BCN_SETTINGS_USE_NETWORK)
149
  {
@@ -151,17 +152,17 @@ class bcn_network_admin extends bcn_admin
151
  }
152
  else if(defined('BCN_SETTINGS_FAVOR_LOCAL') && BCN_SETTINGS_FAVOR_LOCAL)
153
  {
154
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Individual site settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_isitemayoveride');
155
  }
156
  else if(defined('BCN_SETTINGS_FAVOR_NETWORK') && BCN_SETTINGS_FAVOR_NETWORK)
157
  {
158
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Individual site settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_nsmayoveride');
159
  }
160
  //Fall through if no settings mode was set
161
  else
162
  {
163
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: No BCN_SETTINGS_* define statement found, defaulting to BCN_SETTINGS_USE_LOCAL.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_nosetting');
164
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Warning: Individual site settings will override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_isiteoveride');
165
  }
166
  }
167
  }
1
  <?php
2
  /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
22
  {
23
  require_once(dirname(__FILE__) . '/class.bcn_admin.php');
24
  }
25
+ use mtekk\adminKit\{adminKit, form, message, setting};
26
  /**
27
  * The administrative interface class
28
  *
29
  */
30
  class bcn_network_admin extends bcn_admin
31
  {
32
+ const version = '7.0.0';
33
  protected $full_name = 'Breadcrumb NavXT Network Settings';
34
  protected $access_level = 'manage_network_options';
35
  /**
37
  * @param bcn_breadcrumb_trail $breadcrumb_trail a breadcrumb trail object
38
  * @param string $basename The basename of the plugin
39
  */
40
+ function __construct(array &$opts, $basename, array &$settings)
41
  {
42
  //We're going to make sure we load the parent's constructor
43
+ parent::__construct($opts, $basename, $settings);
44
  //Change to the proper name
45
  $this->full_name = __('Breadcrumb NavXT Network Settings', 'breadcrumb-navxt');
46
  //Remove the hook added by the parent as we don't want this classes settings page everywhere
144
  {
145
  if(defined('BCN_SETTINGS_USE_LOCAL') && BCN_SETTINGS_USE_LOCAL)
146
  {
147
+ $this->messages[] = new message(esc_html__('Warning: Individual site settings will override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_isiteoveride');
148
  }
149
  else if(defined('BCN_SETTINGS_USE_NETWORK') && BCN_SETTINGS_USE_NETWORK)
150
  {
152
  }
153
  else if(defined('BCN_SETTINGS_FAVOR_LOCAL') && BCN_SETTINGS_FAVOR_LOCAL)
154
  {
155
+ $this->messages[] = new message(esc_html__('Warning: Individual site settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_isitemayoveride');
156
  }
157
  else if(defined('BCN_SETTINGS_FAVOR_NETWORK') && BCN_SETTINGS_FAVOR_NETWORK)
158
  {
159
+ $this->messages[] = new message(esc_html__('Warning: Individual site settings may override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_nsmayoveride');
160
  }
161
  //Fall through if no settings mode was set
162
  else
163
  {
164
+ $this->messages[] = new message(esc_html__('Warning: No BCN_SETTINGS_* define statement found, defaulting to BCN_SETTINGS_USE_LOCAL.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_nosetting');
165
+ $this->messages[] = new message(esc_html__('Warning: Individual site settings will override any settings set in this page.', 'breadcrumb-navxt'), 'warning', true, $this->unique_prefix . '_msg_ns_isiteoveride');
166
  }
167
  }
168
  }
class.bcn_rest_controller.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2015-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -53,15 +53,15 @@ class bcn_rest_controller
53
  /**
54
  * A quick wrapper for register_rest_route to add our inclusion filter
55
  *
 
56
  * @param string $namespace The first URL segment after core prefix. Should be unique
57
  * @param string $route The base URL for route being added
58
  * @param array $args Optional. Either an array of options for the endpoint, or an array of arrays for
59
  * multiple methods. Default empty array.
60
  * @param bool $override Optional. If the route already exists, should we override it?
61
- * @param string $endpoint The endpoint name passed into the bcn_register_rest_endpoint filter
62
  * @return boolean True on success, false on error.
63
  */
64
- protected function register_rest_route($namespace, $route, $args = array(), $override = false, $endpoint)
65
  {
66
  if(apply_filters('bcn_register_rest_endpoint', false, $endpoint, $this::version, $this->methods))
67
  {
@@ -71,7 +71,7 @@ class bcn_rest_controller
71
  }
72
  public function register_routes()
73
  {
74
- $this->register_rest_route( $this->unique_prefix . '/v' . $this::version, '/post/(?P<id>[\d]+)', array(
75
  'args' => array(
76
  'id' => array(
77
  'description' => __('The ID of the post (any type) to retrieve the breadcrumb trail for.', 'breadcrumb-navxt'),
@@ -83,9 +83,9 @@ class bcn_rest_controller
83
  'methods' => $this->methods,
84
  'callback' => array($this, 'display_rest_post'),
85
  'permission_callback' => array($this, 'display_rest_post_permissions_check')
86
- ), false, 'post'
87
  );
88
- $this->register_rest_route( $this->unique_prefix . '/v' . $this::version, '/term/(?P<taxonomy>[\w-]+)/(?P<id>[\d]+)', array(
89
  'args' => array(
90
  'id' => array(
91
  'description' => __('The ID of the term to retrieve the breadcrumb trail for.', 'breadcrumb-navxt'),
@@ -101,10 +101,11 @@ class bcn_rest_controller
101
  )
102
  ),
103
  'methods' => $this->methods,
104
- 'callback' => array($this, 'display_rest_term')
105
- ), false, 'term'
 
106
  );
107
- $this->register_rest_route( $this->unique_prefix . '/v' . $this::version, '/author/(?P<id>\d+)', array(
108
  'args' => array(
109
  'id' => array(
110
  'description' => __('The ID of the author to retrieve the breadcrumb trail for.', 'breadcrumb-navxt'),
@@ -114,8 +115,9 @@ class bcn_rest_controller
114
  )
115
  ),
116
  'methods' => $this->methods,
117
- 'callback' => array($this, 'display_rest_author')
118
- ), false, 'author'
 
119
  );
120
  }
121
  /**
1
  <?php
2
  /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
53
  /**
54
  * A quick wrapper for register_rest_route to add our inclusion filter
55
  *
56
+ * @param string $endpoint The endpoint name passed into the bcn_register_rest_endpoint filter
57
  * @param string $namespace The first URL segment after core prefix. Should be unique
58
  * @param string $route The base URL for route being added
59
  * @param array $args Optional. Either an array of options for the endpoint, or an array of arrays for
60
  * multiple methods. Default empty array.
61
  * @param bool $override Optional. If the route already exists, should we override it?
 
62
  * @return boolean True on success, false on error.
63
  */
64
+ protected function register_rest_route($endpoint, $namespace, $route, $args = array(), $override = false)
65
  {
66
  if(apply_filters('bcn_register_rest_endpoint', false, $endpoint, $this::version, $this->methods))
67
  {
71
  }
72
  public function register_routes()
73
  {
74
+ $this->register_rest_route('post', $this->unique_prefix . '/v' . $this::version, '/post/(?P<id>[\d]+)', array(
75
  'args' => array(
76
  'id' => array(
77
  'description' => __('The ID of the post (any type) to retrieve the breadcrumb trail for.', 'breadcrumb-navxt'),
83
  'methods' => $this->methods,
84
  'callback' => array($this, 'display_rest_post'),
85
  'permission_callback' => array($this, 'display_rest_post_permissions_check')
86
+ ), false
87
  );
88
+ $this->register_rest_route('term', $this->unique_prefix . '/v' . $this::version, '/term/(?P<taxonomy>[\w-]+)/(?P<id>[\d]+)', array(
89
  'args' => array(
90
  'id' => array(
91
  'description' => __('The ID of the term to retrieve the breadcrumb trail for.', 'breadcrumb-navxt'),
101
  )
102
  ),
103
  'methods' => $this->methods,
104
+ 'callback' => array($this, 'display_rest_term'),
105
+ 'permission_callback' => '__return_true'
106
+ ), false
107
  );
108
+ $this->register_rest_route('author', $this->unique_prefix . '/v' . $this::version, '/author/(?P<id>\d+)', array(
109
  'args' => array(
110
  'id' => array(
111
  'description' => __('The ID of the author to retrieve the breadcrumb trail for.', 'breadcrumb-navxt'),
115
  )
116
  ),
117
  'methods' => $this->methods,
118
+ 'callback' => array($this, 'display_rest_author'),
119
+ 'permission_callback' => '__return_true'
120
+ ), false
121
  );
122
  }
123
  /**
class.bcn_widget.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2015-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
19
  require_once(dirname(__FILE__) . '/includes/block_direct_access.php');
20
  class bcn_widget extends WP_Widget
21
  {
22
- const version = '6.6.0';
23
  protected $allowed_html = array();
24
  protected $defaults = array('title' => '', 'pretext' => '', 'type' => 'microdata', 'linked' => true, 'reverse' => false, 'front' => false, 'force' => false);
25
  //Default constructor
@@ -99,15 +99,17 @@ class bcn_widget extends WP_Widget
99
  $old_instance['title'] = strip_tags($new_instance['title']);
100
  $old_instance['pretext'] = wp_kses($new_instance['pretext'], $this->allowed_html);
101
  $old_instance['type'] = strip_tags($new_instance['type']);
102
- $old_instance['linked'] = isset($new_instance['linked']);
103
- $old_instance['reverse'] = isset($new_instance['reverse']);
104
- $old_instance['front'] = isset($new_instance['front']);
105
- $old_instance['force'] = isset($new_instance['force']);
 
106
  return $old_instance;
107
  }
108
  function form($instance)
109
  {
110
- $instance = wp_parse_args((array) $instance, $this->defaults);?>
 
111
  <p>
112
  <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"> <?php _e('Title:', 'breadcrumb-navxt'); ?></label>
113
  <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']);?>" />
@@ -127,13 +129,13 @@ class bcn_widget extends WP_Widget
127
  </select>
128
  </p>
129
  <p>
130
- <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')); ?>" value="true" <?php checked(true, $instance['linked']);?> />
131
  <label for="<?php echo esc_attr($this->get_field_id('linked')); ?>"> <?php _e('Link the breadcrumbs', 'breadcrumb-navxt'); ?></label><br />
132
- <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')); ?>" value="true" <?php checked(true, $instance['reverse']);?> />
133
  <label for="<?php echo esc_attr($this->get_field_id('reverse')); ?>"> <?php _e('Reverse the order of the trail', 'breadcrumb-navxt'); ?></label><br />
134
- <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')); ?>" value="true" <?php checked(true, $instance['front']);?> />
135
  <label for="<?php echo esc_attr($this->get_field_id('front')); ?>"> <?php _e('Hide the trail on the front page', 'breadcrumb-navxt'); ?></label><br />
136
- <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')); ?>" value="true" <?php checked(true, $instance['force']);?> />
137
  <label for="<?php echo esc_attr($this->get_field_id('force')); ?>"> <?php _e('Ignore breadcrumb cache', 'breadcrumb-navxt'); ?></label><br />
138
  </p>
139
  <?php
1
  <?php
2
  /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
19
  require_once(dirname(__FILE__) . '/includes/block_direct_access.php');
20
  class bcn_widget extends WP_Widget
21
  {
22
+ const version = '7.0.0';
23
  protected $allowed_html = array();
24
  protected $defaults = array('title' => '', 'pretext' => '', 'type' => 'microdata', 'linked' => true, 'reverse' => false, 'front' => false, 'force' => false);
25
  //Default constructor
99
  $old_instance['title'] = strip_tags($new_instance['title']);
100
  $old_instance['pretext'] = wp_kses($new_instance['pretext'], $this->allowed_html);
101
  $old_instance['type'] = strip_tags($new_instance['type']);
102
+ //Have to check more than if it is set as it appears this must effectively run twice since WordPress 5.8
103
+ $old_instance['linked'] = isset($new_instance['linked']) && $new_instance['linked'] !== false;
104
+ $old_instance['reverse'] = isset($new_instance['reverse']) && $new_instance['reverse'] !== false;
105
+ $old_instance['front'] = isset($new_instance['front']) && $new_instance['front'] !== false;
106
+ $old_instance['force'] = isset($new_instance['force']) && $new_instance['force'] !== false;
107
  return $old_instance;
108
  }
109
  function form($instance)
110
  {
111
+ $instance = wp_parse_args((array) $instance, $this->defaults);
112
+ ?>
113
  <p>
114
  <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"> <?php _e('Title:', 'breadcrumb-navxt'); ?></label>
115
  <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']);?>" />
129
  </select>
130
  </p>
131
  <p>
132
+ <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']);?> />
133
  <label for="<?php echo esc_attr($this->get_field_id('linked')); ?>"> <?php _e('Link the breadcrumbs', 'breadcrumb-navxt'); ?></label><br />
134
+ <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']);?> />
135
  <label for="<?php echo esc_attr($this->get_field_id('reverse')); ?>"> <?php _e('Reverse the order of the trail', 'breadcrumb-navxt'); ?></label><br />
136
+ <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']);?> />
137
  <label for="<?php echo esc_attr($this->get_field_id('front')); ?>"> <?php _e('Hide the trail on the front page', 'breadcrumb-navxt'); ?></label><br />
138
+ <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']);?> />
139
  <label for="<?php echo esc_attr($this->get_field_id('force')); ?>"> <?php _e('Ignore breadcrumb cache', 'breadcrumb-navxt'); ?></label><br />
140
  </p>
141
  <?php
includes/{mtekk_adminkit_engroups.js → adminKit/assets/mtekk_adminkit_engroups.js} RENAMED
File without changes
includes/{mtekk_adminkit_engroups.min.js → adminKit/assets/mtekk_adminkit_engroups.min.js} RENAMED
File without changes
includes/{mtekk_adminkit_messages.js → adminKit/assets/mtekk_adminkit_messages.js} RENAMED
File without changes
includes/{mtekk_adminkit_messages.min.js → adminKit/assets/mtekk_adminkit_messages.min.js} RENAMED
File without changes
includes/{mtekk_adminkit_tabs.css → adminKit/assets/mtekk_adminkit_tabs.css} RENAMED
File without changes
includes/{mtekk_adminkit_tabs.js → adminKit/assets/mtekk_adminkit_tabs.js} RENAMED
File without changes
includes/{mtekk_adminkit_tabs.min.css → adminKit/assets/mtekk_adminkit_tabs.min.css} RENAMED
File without changes
includes/{mtekk_adminkit_tabs.min.js → adminKit/assets/mtekk_adminkit_tabs.min.js} RENAMED
File without changes
includes/{class.mtekk_adminkit.php → adminKit/class-mtekk_adminkit.php} RENAMED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- Copyright 2015-2020 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
@@ -16,15 +16,58 @@
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
  */
19
- require_once(dirname(__FILE__) . '/block_direct_access.php');
20
- //Include admin base class
21
- if(!class_exists('mtekk_adminKit_message'))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  {
23
- require_once(dirname(__FILE__) . '/class.mtekk_adminkit_message.php');
24
  }
25
- abstract class mtekk_adminKit
 
26
  {
27
- const version = '2.1.1';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  protected $full_name;
29
  protected $short_name;
30
  protected $plugin_basename;
@@ -36,6 +79,8 @@ abstract class mtekk_adminKit
36
  protected $message;
37
  protected $support_url;
38
  protected $allowed_html;
 
 
39
  function __construct()
40
  {
41
  $this->message = array();
@@ -49,6 +94,7 @@ abstract class mtekk_adminKit
49
  //Initilizes l10n domain
50
  $this->local();
51
  add_action('wp_loaded', array($this, 'wp_loaded'));
 
52
  //Register Help Output
53
  //add_action('add_screen_help_and_options', array($this, 'help'));
54
  }
@@ -62,7 +108,7 @@ abstract class mtekk_adminKit
62
  */
63
  function get_admin_class_version()
64
  {
65
- return mtekk_adminKit::version;
66
  }
67
  /**
68
  * Checks if the administrator has the access capability, and adds it if they don't
@@ -188,19 +234,17 @@ abstract class mtekk_adminKit
188
  $suffix = '.min';
189
  }
190
  //Register JS for more permanently dismissing messages
191
- wp_register_script('mtekk_adminkit_messages', plugins_url('/mtekk_adminkit_messages' . $suffix . '.js', dirname(__FILE__) . '/mtekk_adminkit_messages' . $suffix . '.js'), array('jquery'), self::version, true);
192
  //Register JS for enable/disable settings groups
193
- wp_register_script('mtekk_adminkit_engroups', plugins_url('/mtekk_adminkit_engroups' . $suffix . '.js', dirname(__FILE__) . '/mtekk_adminkit_engroups' . $suffix . '.js'), array('jquery'), self::version, true);
194
  //Register JS for tabs
195
- wp_register_script('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.js', dirname(__FILE__) . '/mtekk_adminkit_tabs' . $suffix . '.js'), array('jquery-ui-tabs'), self::version, true);
196
  //Register CSS for tabs
197
- wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.css', dirname(__FILE__) . '/mtekk_adminkit_tabs' . $suffix . '.css'));
198
  //Register options
199
  register_setting($this->unique_prefix . '_options', $this->unique_prefix . '_options', '');
200
  //Synchronize up our settings with the database as we're done modifying them now
201
  $this->opt = $this::parse_args($this->get_option($this->unique_prefix . '_options'), $this->opt);
202
- //Run the opts fix filter
203
- $this->opts_fix($this->opt);
204
  add_action('wp_ajax_mtekk_admin_message_dismiss', array($this, 'dismiss_message'));
205
  }
206
  /**
@@ -267,10 +311,13 @@ abstract class mtekk_adminKit
267
  */
268
  function is_installed()
269
  {
270
-
 
271
  }
272
  /**
273
  * This sets up and upgrades the database settings, runs on every activation
 
 
274
  */
275
  function install()
276
  {
@@ -281,11 +328,9 @@ abstract class mtekk_adminKit
281
  //If there are no settings, copy over the default settings
282
  if(!is_array($opts))
283
  {
284
- //Grab defaults from the object
285
- $opts = $this->opt;
286
- //Add the options
287
- $this->add_option($this->unique_prefix . '_options', $opts);
288
- $this->add_option($this->unique_prefix . '_options_bk', $opts, '', 'no');
289
  //Add the version, no need to autoload the db version
290
  $this->update_option($this->unique_prefix . '_version', $this::version, 'no');
291
  }
@@ -332,7 +377,7 @@ abstract class mtekk_adminKit
332
  if($version && version_compare($version, $this::version, '<') && is_array($this->opt))
333
  {
334
  //Throw an error since the DB version is out of date
335
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Your settings are for an older version of this plugin and need to be migrated.', $this->identifier)
336
  . $this->admin_anchor('upgrade', __('Migrate the settings now.', $this->identifier), __('Migrate now.', $this->identifier)), 'warning');
337
  //Output any messages that there may be
338
  $this->messages();
@@ -342,25 +387,25 @@ abstract class mtekk_adminKit
342
  else if($version && version_compare($version, $this::version, '>') && is_array($this->opt))
343
  {
344
  //Let the user know that their settings are for a newer version
345
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Your settings are for a newer version of this plugin.', $this->identifier)
346
  . $this->admin_anchor('upgrade', __('Migrate the settings now.', $this->identifier), __('Attempt back migration now.', $this->identifier)), 'warning');
347
  //Output any messages that there may be
348
  $this->messages();
349
  return true;
350
  }
351
- else if(!is_array($this->opt))
352
  {
353
  //Throw an error since it appears the options were never registered
354
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Your plugin install is incomplete.', $this->identifier)
355
  . $this->admin_anchor('upgrade', __('Load default settings now.', $this->identifier), __('Complete now.', $this->identifier)), 'error');
356
  //Output any messages that there may be
357
  $this->messages();
358
  return false;
359
  }
360
- else if(!$this->opts_validate($this->opt))
361
  {
362
  //Throw an error since it appears the options contain invalid data
363
- $this->messages[] = new mtekk_adminKit_message(esc_html__('One or more of your plugin settings are invalid.', $this->identifier)
364
  . $this->admin_anchor('fix', __('Attempt to fix settings now.', $this->identifier), __('Fix now.', $this->identifier)), 'error');
365
  //Output any messages that there may be
366
  $this->messages();
@@ -369,19 +414,28 @@ abstract class mtekk_adminKit
369
  return true;
370
  }
371
  /**
372
- * A prototype function. End user should override if they need this feature.
373
- */
374
- function opts_validate(&$opts)
375
- {
376
- return true;
377
- }
378
- /**
379
- * A prototype function. End user should override if they need this feature.
380
  *
381
- * @param array $opts
 
382
  */
383
- function opts_fix(&$opts)
384
  {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  }
386
  /**
387
  * Synchronizes the backup options entry with the current options entry
@@ -392,88 +446,28 @@ abstract class mtekk_adminKit
392
  $this->update_option($this->unique_prefix . '_options_bk', $this->get_option($this->unique_prefix . '_options'));
393
  }
394
  /**
395
- * Runs recursivly through the opts array, sanitizing and merging in updates from the $input array
396
  *
397
- * @param array $opts good, clean array
398
- * @param array $input unsanitzed input array, not trusted at all
399
- * @todo This function should probably get a filter thrown within it to be more extensible
400
  */
401
- protected function opts_update_loop(&$opts, $input)
402
  {
403
- //Loop through all of the existing options (avoids random setting injection)
404
- foreach($opts as $option => $value)
405
  {
406
- //If we have an array, dive into another recursive loop
407
- if(isset($input[$option]) && is_array($value))
408
- {
409
- $this->opts_update_loop($opts[$option], $input[$option]);
410
- }
411
- //We must check for unset settings, but booleans are ok to be unset
412
- else if(isset($input[$option]) || $option[0] == 'b')
413
  {
414
- switch($option[0])
415
  {
416
- //Handle the boolean options
417
- case 'b':
418
- $opts[$option] = isset($input[$option]);
419
- break;
420
- //Handle the integer options
421
- case 'i':
422
- $opts[$option] = (int) $input[$option];
423
- break;
424
- //Handle the absolute integer options
425
- case 'a':
426
- $opts[$option] = (int) abs($input[$option]);
427
- break;
428
- //Handle the floating point options
429
- case 'f':
430
- $opts[$option] = (float) $input[$option];
431
- break;
432
- //Handle the HTML options
433
- case 'h':
434
- $opts[$option] = wp_kses(stripslashes($input[$option]), $this->allowed_html);
435
- break;
436
- //Handle the HTML options that must not be null
437
- case 'H':
438
- if(isset($input[$option]))
439
- {
440
- $opts[$option] = wp_kses(stripslashes($input[$option]), $this->allowed_html);
441
- }
442
- break;
443
- //Handle the text options that must not be null
444
- case 'S':
445
- if(isset($input[$option]))
446
- {
447
- $opts[$option] = esc_html($input[$option]);
448
- }
449
- break;
450
- //Deal with strings that can be null
451
- case 's':
452
- $opts[$option] = esc_html($input[$option]);
453
- break;
454
- //Deal with enumerated types
455
- case 'E':
456
- $opts[$option] = $this->opts_sanitize_enum($input[$option], $option);
457
- break;
458
- //By default we have nothing to do, allows for internal settings
459
- default:
460
- break;
461
  }
462
  }
 
 
 
 
463
  }
464
  }
465
- /**
466
- * Simple sanitization function for enumerated types, end users should overload this
467
- * with something more usefull
468
- *
469
- * @param string $value The input value from the form
470
- * @param string $option The option name
471
- * @return string The sanitized enumerated string
472
- */
473
- private function opts_sanitize_enum($value, $option)
474
- {
475
- return esc_html($value);
476
- }
477
  /**
478
  * A better version of parse_args, will recrusivly follow arrays
479
  *
@@ -497,7 +491,7 @@ abstract class mtekk_adminKit
497
  }
498
  if(is_array($defaults))
499
  {
500
- return mtekk_adminKit::array_merge_recursive($defaults, $r);
501
  }
502
  return $r;
503
  }
@@ -515,7 +509,7 @@ abstract class mtekk_adminKit
515
  {
516
  if(array_key_exists($key, $arg1) && is_array($value))
517
  {
518
- $arg1[$key] = mtekk_adminKit::array_merge_recursive($arg1[$key], $value);
519
  }
520
  else
521
  {
@@ -525,17 +519,95 @@ abstract class mtekk_adminKit
525
  return $arg1;
526
  }
527
  /**
528
- * An action that fires just before the options backup, use to add in dynamically detected options
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
  *
530
- * @param array $opts the options array, passed in by reference
531
- * @return null
 
532
  */
533
- function opts_update_prebk(&$opts)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
534
  {
535
- //Just a prototype function
 
 
 
 
536
  }
537
  /**
538
  * Updates the database settings from the webform
 
 
 
 
 
 
539
  */
540
  function opts_update()
541
  {
@@ -543,47 +615,67 @@ abstract class mtekk_adminKit
543
  $this->security();
544
  //Do a nonce check, prevent malicious link/form problems
545
  check_admin_referer($this->unique_prefix . '_options-options');
 
 
546
  //Update local options from database
547
- $this->opt = $this::parse_args($this->get_option($this->unique_prefix . '_options'), $this->opt);
548
- $this->opts_update_prebk($this->opt);
549
  //Update our backup options
550
  $this->update_option($this->unique_prefix . '_options_bk', $this->opt);
551
  $opt_prev = $this->opt;
552
  //Grab our incomming array (the data is dirty)
553
  $input = $_POST[$this->unique_prefix . '_options'];
554
  //Run the update loop
555
- $this->opts_update_loop($this->opt, $input);
 
 
 
 
556
  //Commit the option changes
557
  $updated = $this->update_option($this->unique_prefix . '_options', $this->opt);
558
  //Check if known settings match attempted save
559
- if($updated && count(array_diff_key($input, $this->opt)) == 0)
560
  {
561
  //Let the user know everything went ok
562
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings successfully saved.', $this->identifier)
563
  . $this->admin_anchor('undo', __('Undo the options save.', $this->identifier), __('Undo', $this->identifier)), 'success');
564
  }
565
- else if(!$updated && count(array_diff_key($opt_prev, $this->opt)) == 0)
566
  {
567
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings did not change, nothing to save.', $this->identifier), 'info');
568
  }
569
  else if(!$updated)
570
  {
571
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings were not saved.', $this->identifier), 'error');
572
  }
573
  else
574
  {
575
  //Let the user know the following were not saved
576
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Some settings were not saved.', $this->identifier)
577
  . $this->admin_anchor('undo', __('Undo the options save.', $this->identifier), __('Undo', $this->identifier)), 'warning');
578
  $temp = esc_html__('The following settings were not saved:', $this->identifier);
579
- foreach(array_diff_key($input, $this->opt) as $setting => $value)
580
  {
581
  $temp .= '<br />' . $setting;
582
  }
583
- $this->messages[] = new mtekk_adminKit_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');
584
  }
585
  add_action('admin_notices', array($this, 'messages'));
586
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
587
  /**
588
  * Exports a XML options document
589
  */
@@ -683,13 +775,13 @@ abstract class mtekk_adminKit
683
  //Commit the loaded options to the database
684
  $this->update_option($this->unique_prefix . '_options', $this->opt);
685
  //Everything was successful, let the user know
686
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier)
687
  . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success');
688
  }
689
  else
690
  {
691
  //Throw an error since we could not load the file for various reasons
692
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Importing settings from file failed.', $this->identifier), 'error');
693
  }
694
  //Reset to the default error handler after we're done
695
  restore_error_handler();
@@ -706,9 +798,9 @@ abstract class mtekk_adminKit
706
  //Set the backup options in the DB to the current options
707
  $this->opts_backup();
708
  //Load in the hard coded default option values
709
- $this->update_option($this->unique_prefix . '_options', $this->opt);
710
  //Reset successful, let the user know
711
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings successfully reset to the default values.', $this->identifier)
712
  . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier)), 'success');
713
  add_action('admin_notices', array($this, 'messages'));
714
  }
@@ -726,7 +818,7 @@ abstract class mtekk_adminKit
726
  //Set the backup options to the undone options
727
  $this->update_option($this->unique_prefix . '_options_bk', $opt);
728
  //Send the success/undo message
729
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings successfully undid the last operation.', $this->identifier)
730
  . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier)), 'success');
731
  add_action('admin_notices', array($this, 'messages'));
732
  }
@@ -746,6 +838,8 @@ abstract class mtekk_adminKit
746
  }
747
  /**
748
  * Forces a database settings upgrade
 
 
749
  */
750
  function opts_upgrade_wrapper()
751
  {
@@ -762,14 +856,14 @@ abstract class mtekk_adminKit
762
  //Store the options
763
  $this->update_option($this->unique_prefix . '_options', $this->opt);
764
  //Send the success message
765
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Settings successfully migrated.', $this->identifier), 'success');
766
  }
767
  else
768
  {
769
  //Run the install script
770
  $this->install();
771
  //Send the success message
772
- $this->messages[] = new mtekk_adminKit_message(esc_html__('Default settings successfully installed.', $this->identifier), 'success');
773
  }
774
  add_action('admin_notices', array($this, 'messages'));
775
  }
@@ -793,7 +887,7 @@ abstract class mtekk_adminKit
793
  //Grab the submitted UID
794
  $uid = esc_attr($_POST['uid']);
795
  //Create a dummy message, with the discovered UID
796
- $message = new mtekk_adminKit_message('', '', true, $uid);
797
  //Dismiss the message
798
  $message->dismiss();
799
  wp_die();
@@ -863,9 +957,12 @@ abstract class mtekk_adminKit
863
  * Returns a valid xHTML element ID
864
  *
865
  * @param object $option
 
 
866
  */
867
  static public function get_valid_id($option)
868
  {
 
869
  if(is_numeric($option[0]))
870
  {
871
  return 'p' . $option;
@@ -900,10 +997,13 @@ abstract class mtekk_adminKit
900
  * This will output a well formed hidden option
901
  *
902
  * @param string $option
 
 
903
  */
904
  function input_hidden($option)
905
  {
906
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
907
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
908
  printf('<input type="hidden" name="%1$s" id="%2$s" value="%3$s" />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]));
909
  }
@@ -912,9 +1012,12 @@ abstract class mtekk_adminKit
912
  *
913
  * @param string $opt_id
914
  * @param string $label
 
 
915
  */
916
  function label($opt_id, $label)
917
  {
 
918
  printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);
919
  }
920
  /**
@@ -925,10 +1028,13 @@ abstract class mtekk_adminKit
925
  * @param string $class (optional)
926
  * @param bool $disable (optional)
927
  * @param string $description (optional)
 
 
928
  */
929
  function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '')
930
  {
931
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
932
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
933
  if($disable)
934
  {
@@ -957,10 +1063,13 @@ abstract class mtekk_adminKit
957
  * @param int|string $min (optional)
958
  * @param int|string $max (optional)
959
  * @param int|string $step (optional)
 
 
960
  */
961
  function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')
962
  {
963
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
964
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
965
  $extras = '';
966
  if($min !== '')
@@ -999,10 +1108,13 @@ abstract class mtekk_adminKit
999
  * @param string $rows (optional)
1000
  * @param bool $disable (optional)
1001
  * @param string $description (optional)
 
 
1002
  */
1003
  function textbox($label, $option, $height = '3', $disable = false, $description = '', $class = '')
1004
  {
1005
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
1006
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1007
  $class .= ' large-text';
1008
  if($disable)
@@ -1029,10 +1141,13 @@ abstract class mtekk_adminKit
1029
  * @param string $rows (optional)
1030
  * @param bool $disable (optional)
1031
  * @param string $description (optional)
 
 
1032
  */
1033
  function tinymce($label, $option, $height = '3', $disable = false, $description = '')
1034
  {
1035
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
1036
  $class = 'mtekk_mce';
1037
  if($disable)
1038
  {
@@ -1059,10 +1174,13 @@ abstract class mtekk_adminKit
1059
  * @param bool $disable (optional)
1060
  * @param string $description (optional)
1061
  * @param string $class (optional)
 
 
1062
  */
1063
  function input_check($label, $option, $instruction, $disable = false, $description = '', $class = '')
1064
  {
1065
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
1066
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1067
  if($disable)
1068
  {
@@ -1091,10 +1209,13 @@ abstract class mtekk_adminKit
1091
  * @param string $instruction
1092
  * @param object $disable (optional)
1093
  * @param string $class (optional)
 
 
1094
  */
1095
  function input_radio($option, $value, $instruction, $disable = false, $class = '')
1096
  {
1097
- $opt_id = mtekk_adminKit::get_valid_id($option);
 
1098
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1099
  $class .= ' togx';
1100
  if($disable)
@@ -1118,15 +1239,18 @@ abstract class mtekk_adminKit
1118
  * @param string $description (optional)
1119
  * @param array $titles (optional) The array of titiles for the options, if they should be different from the values
1120
  * @param string $class (optional) Extra class to apply to the elements
 
 
1121
  */
1122
  function input_select($label, $option, $values, $disable = false, $description = '', $titles = false, $class = '')
1123
  {
 
1124
  //If we don't have titles passed in, we'll use option names as values
1125
  if(!$titles)
1126
  {
1127
  $titles = $values;
1128
  }
1129
- $opt_id = mtekk_adminKit::get_valid_id($option);
1130
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1131
  if($disable)
1132
  {
@@ -1153,9 +1277,12 @@ abstract class mtekk_adminKit
1153
  * @param array $exclude(optional) array of names in $options array to be excluded
1154
  *
1155
  * @return string The assembled HTML for the select options
 
 
1156
  */
1157
  function select_options($optionname, $options, $values, $exclude = array())
1158
  {
 
1159
  $options_html = '';
1160
  $value = $this->opt[$optionname];
1161
  //Now do the rest
1
  <?php
2
  /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
 
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
  */
19
+ namespace mtekk\adminKit;
20
+ use mtekk\adminKit\setting\setting;
21
+
22
+ require_once( __DIR__ . '/../block_direct_access.php');
23
+ //Include message class
24
+ if(!class_exists('message'))
25
+ {
26
+ require_once(__DIR__ . '/class-mtekk_adminkit_message.php');
27
+ }
28
+ //Include setting class
29
+ if(!class_exists('setting\setting_absint'))
30
+ {
31
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_absint.php');
32
+ }
33
+ //Include setting class
34
+ if(!class_exists('setting\setting_bool'))
35
+ {
36
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_bool.php');
37
+ }
38
+ //Include setting class
39
+ if(!class_exists('setting\setting_enum'))
40
  {
41
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_enum.php');
42
  }
43
+ //Include setting class
44
+ if(!class_exists('setting\setting_float'))
45
  {
46
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_float.php');
47
+ }
48
+ //Include setting class
49
+ if(!class_exists('settingsetting_\html'))
50
+ {
51
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_html.php');
52
+ }
53
+ //Include setting class
54
+ if(!class_exists('setting\setting_int'))
55
+ {
56
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_int.php');
57
+ }
58
+ //Include setting class
59
+ if(!class_exists('setting\setting_string'))
60
+ {
61
+ require_once(__DIR__ . '/setting/class-mtekk_adminkit_setting_string.php');
62
+ }
63
+ //Include from class
64
+ if(!class_exists('form'))
65
+ {
66
+ require_once(__DIR__ . '/class-mtekk_adminkit_form.php');
67
+ }
68
+ abstract class adminKit
69
+ {
70
+ const version = '2.9.50';
71
  protected $full_name;
72
  protected $short_name;
73
  protected $plugin_basename;
79
  protected $message;
80
  protected $support_url;
81
  protected $allowed_html;
82
+ protected $settings = array();
83
+ protected $form;
84
  function __construct()
85
  {
86
  $this->message = array();
94
  //Initilizes l10n domain
95
  $this->local();
96
  add_action('wp_loaded', array($this, 'wp_loaded'));
97
+ $this->form = new form($this->unique_prefix);
98
  //Register Help Output
99
  //add_action('add_screen_help_and_options', array($this, 'help'));
100
  }
108
  */
109
  function get_admin_class_version()
110
  {
111
+ return adminKit::version;
112
  }
113
  /**
114
  * Checks if the administrator has the access capability, and adds it if they don't
234
  $suffix = '.min';
235
  }
236
  //Register JS for more permanently dismissing messages
237
+ wp_register_script('mtekk_adminkit_messages', plugins_url('/mtekk_adminkit_messages' . $suffix . '.js', dirname(__FILE__) . '/assets/mtekk_adminkit_messages' . $suffix . '.js'), array('jquery'), self::version, true);
238
  //Register JS for enable/disable settings groups
239
+ wp_register_script('mtekk_adminkit_engroups', plugins_url('/mtekk_adminkit_engroups' . $suffix . '.js', dirname(__FILE__) . '/assets/mtekk_adminkit_engroups' . $suffix . '.js'), array('jquery'), self::version, true);
240
  //Register JS for tabs
241
+ 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);
242
  //Register CSS for tabs
243
+ wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs' . $suffix . '.css', dirname(__FILE__) . '/assets/mtekk_adminkit_tabs' . $suffix . '.css'));
244
  //Register options
245
  register_setting($this->unique_prefix . '_options', $this->unique_prefix . '_options', '');
246
  //Synchronize up our settings with the database as we're done modifying them now
247
  $this->opt = $this::parse_args($this->get_option($this->unique_prefix . '_options'), $this->opt);
 
 
248
  add_action('wp_ajax_mtekk_admin_message_dismiss', array($this, 'dismiss_message'));
249
  }
250
  /**
311
  */
312
  function is_installed()
313
  {
314
+ $opts = $this->get_option($this->unique_prefix . '_options');
315
+ return is_array($opts);
316
  }
317
  /**
318
  * This sets up and upgrades the database settings, runs on every activation
319
+ *
320
+ * FIXME: seems there is a lot of very similar code in opts_upgrade_wrapper
321
  */
322
  function install()
323
  {
328
  //If there are no settings, copy over the default settings
329
  if(!is_array($opts))
330
  {
331
+ //Add the options, we only store differences from defaults now, so start with blank array
332
+ $this->add_option($this->unique_prefix . '_options', array());
333
+ $this->add_option($this->unique_prefix . '_options_bk', array(), '', 'no');
 
 
334
  //Add the version, no need to autoload the db version
335
  $this->update_option($this->unique_prefix . '_version', $this::version, 'no');
336
  }
377
  if($version && version_compare($version, $this::version, '<') && is_array($this->opt))
378
  {
379
  //Throw an error since the DB version is out of date
380
+ $this->messages[] = new message(esc_html__('Your settings are for an older version of this plugin and need to be migrated.', $this->identifier)
381
  . $this->admin_anchor('upgrade', __('Migrate the settings now.', $this->identifier), __('Migrate now.', $this->identifier)), 'warning');
382
  //Output any messages that there may be
383
  $this->messages();
387
  else if($version && version_compare($version, $this::version, '>') && is_array($this->opt))
388
  {
389
  //Let the user know that their settings are for a newer version
390
+ $this->messages[] = new message(esc_html__('Your settings are for a newer version of this plugin.', $this->identifier)
391
  . $this->admin_anchor('upgrade', __('Migrate the settings now.', $this->identifier), __('Attempt back migration now.', $this->identifier)), 'warning');
392
  //Output any messages that there may be
393
  $this->messages();
394
  return true;
395
  }
396
+ else if(!is_array($this->settings))
397
  {
398
  //Throw an error since it appears the options were never registered
399
+ $this->messages[] = new message(esc_html__('Your plugin install is incomplete.', $this->identifier)
400
  . $this->admin_anchor('upgrade', __('Load default settings now.', $this->identifier), __('Complete now.', $this->identifier)), 'error');
401
  //Output any messages that there may be
402
  $this->messages();
403
  return false;
404
  }
405
+ else if(!$this->settings_validate($this->settings))
406
  {
407
  //Throw an error since it appears the options contain invalid data
408
+ $this->messages[] = new message(esc_html__('One or more of your plugin settings are invalid.', $this->identifier)
409
  . $this->admin_anchor('fix', __('Attempt to fix settings now.', $this->identifier), __('Fix now.', $this->identifier)), 'error');
410
  //Output any messages that there may be
411
  $this->messages();
414
  return true;
415
  }
416
  /**
417
+ * Run through all of the settings, check if the value matches the validated value
 
 
 
 
 
 
 
418
  *
419
+ * @param array $settings The settings array
420
+ * @return boolean
421
  */
422
+ function settings_validate(array &$settings)
423
  {
424
+ foreach($settings as $setting)
425
+ {
426
+ if(is_array($setting))
427
+ {
428
+ if(!$this->settings_validate($setting))
429
+ {
430
+ return false;
431
+ }
432
+ }
433
+ else if($setting->get_value() !== $setting->validate($setting->get_value()))
434
+ {
435
+ return false;
436
+ }
437
+ }
438
+ return true;
439
  }
440
  /**
441
  * Synchronizes the backup options entry with the current options entry
446
  $this->update_option($this->unique_prefix . '_options_bk', $this->get_option($this->unique_prefix . '_options'));
447
  }
448
  /**
449
+ * The new, simpler settings update loop, handles the new settings array and replaces the old opts_update_loop
450
  *
451
+ * @param array $settings
452
+ * @param array $input
 
453
  */
454
+ protected function settings_update_loop(&$settings, $input)
455
  {
456
+ foreach($settings as $key => $setting)
 
457
  {
458
+ if(is_array($setting))
 
 
 
 
 
 
459
  {
460
+ if(isset($input[$key]))
461
  {
462
+ $this->settings_update_loop($settings[$key], $input[$key]);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
463
  }
464
  }
465
+ else
466
+ {
467
+ $setting->maybe_update_from_form_input($input);
468
+ }
469
  }
470
  }
 
 
 
 
 
 
 
 
 
 
 
 
471
  /**
472
  * A better version of parse_args, will recrusivly follow arrays
473
  *
491
  }
492
  if(is_array($defaults))
493
  {
494
+ return adminKit::array_merge_recursive($defaults, $r);
495
  }
496
  return $r;
497
  }
509
  {
510
  if(array_key_exists($key, $arg1) && is_array($value))
511
  {
512
+ $arg1[$key] = adminKit::array_merge_recursive($arg1[$key], $value);
513
  }
514
  else
515
  {
519
  return $arg1;
520
  }
521
  /**
522
+ * Extracts settings values to form opts array, for old options compatibility
523
+ *
524
+ * @param array $settings The settings array
525
+ * @return array
526
+ */
527
+ static function settings_to_opts($settings)
528
+ {
529
+ $opts = array();
530
+ foreach ($settings as $key => $setting)
531
+ {
532
+ if(is_array($setting))
533
+ {
534
+ $opts[$key] = adminKit::settings_to_opts($setting);
535
+ }
536
+ else
537
+ {
538
+ $opts[$key] = $setting->get_value();
539
+ }
540
+ }
541
+ return $opts;
542
+ }
543
+ /**
544
+ * Loop through the settings and applying opts values if found
545
+ *
546
+ * @param array $opts The opts array
547
+ */
548
+ function load_opts_into_settings($opts)
549
+ {
550
+ foreach($opts as $key => $value)
551
+ {
552
+ if(isset($this->settings[$key]) && $this->settings[$key] instanceof setting\setting)
553
+ {
554
+ $this->settings[$key]->set_value($this->settings[$key]->validate($value));
555
+ }
556
+ }
557
+ }
558
+ /**
559
+ * Compares two settings by name and value to see if they are equal
560
  *
561
+ * @param \mtekk\adminKit\setting\setting $a
562
+ * @param \mtekk\adminKit\setting\setting $b
563
+ * @return number
564
  */
565
+ function setting_equal_check($a, $b)
566
+ {
567
+ if(is_array($a) || is_array($b))
568
+ {
569
+ foreach($a as $key=>$value)
570
+ {
571
+ if($value instanceof setting && isset($b[$key]) && $b[$key] instanceof setting)
572
+ {
573
+ return $this->setting_equal_check($value, $b[$key]);
574
+ }
575
+ else
576
+ {
577
+ return -1;
578
+ }
579
+ }
580
+ return -1;
581
+ }
582
+ if($a->get_name() === $b->get_name() && $a->get_value() === $b->get_value())
583
+ {
584
+ return 0;
585
+ }
586
+ else if($a->get_name() === $b->get_name() && $a->get_value() > $b->get_value())
587
+ {
588
+ return 1;
589
+ }
590
+ else
591
+ {
592
+ return -1;
593
+ }
594
+ }
595
+ static function setting_cloner($setting)
596
  {
597
+ if(is_array($setting))
598
+ {
599
+ return array_map('mtekk\adminKit\adminKit::setting_cloner', $setting);
600
+ }
601
+ return clone $setting;
602
  }
603
  /**
604
  * Updates the database settings from the webform
605
+ *
606
+ * The general flow of data is:
607
+ * 1) Establish default values
608
+ * 2) Merge in updates from webform
609
+ * 3) Compute difference between defaults and results of #3
610
+ * 4) Save to database the difference generated in #4
611
  */
612
  function opts_update()
613
  {
615
  $this->security();
616
  //Do a nonce check, prevent malicious link/form problems
617
  check_admin_referer($this->unique_prefix . '_options-options');
618
+ //Must clone the defaults since PHP normally shallow copies
619
+ $default_settings = array_map('mtekk\adminKit\adminKit::setting_cloner', $this->settings);
620
  //Update local options from database
621
+ $this->opt = adminKit::parse_args($this->get_option($this->unique_prefix . '_options'), $this->opt);
622
+ $this->opt = apply_filters($this->unique_prefix . '_opts_update_prebk', $this->opt);
623
  //Update our backup options
624
  $this->update_option($this->unique_prefix . '_options_bk', $this->opt);
625
  $opt_prev = $this->opt;
626
  //Grab our incomming array (the data is dirty)
627
  $input = $_POST[$this->unique_prefix . '_options'];
628
  //Run the update loop
629
+ $this->settings_update_loop($this->settings, $input);
630
+ $new_settings = apply_filters($this->unique_prefix . '_opts_update_to_save', array_udiff_assoc($this->settings, $default_settings, array($this, 'setting_equal_check')));
631
+ //FIXME: Eventually we'll save the object array, but not today
632
+ //Convert to opts array for saving
633
+ $this->opt = adminKit::settings_to_opts($new_settings);
634
  //Commit the option changes
635
  $updated = $this->update_option($this->unique_prefix . '_options', $this->opt);
636
  //Check if known settings match attempted save
637
+ if($updated && count(array_diff_key($input, $this->settings)) == 0)
638
  {
639
  //Let the user know everything went ok
640
+ $this->messages[] = new message(esc_html__('Settings successfully saved.', $this->identifier)
641
  . $this->admin_anchor('undo', __('Undo the options save.', $this->identifier), __('Undo', $this->identifier)), 'success');
642
  }
643
+ else if(!$updated && count(array_diff_key($opt_prev, $this->settings)) == 0)
644
  {
645
+ $this->messages[] = new message(esc_html__('Settings did not change, nothing to save.', $this->identifier), 'info');
646
  }
647
  else if(!$updated)
648
  {
649
+ $this->messages[] = new message(esc_html__('Settings were not saved.', $this->identifier), 'error');
650
  }
651
  else
652
  {
653
  //Let the user know the following were not saved
654
+ $this->messages[] = new message(esc_html__('Some settings were not saved.', $this->identifier)
655
  . $this->admin_anchor('undo', __('Undo the options save.', $this->identifier), __('Undo', $this->identifier)), 'warning');
656
  $temp = esc_html__('The following settings were not saved:', $this->identifier);
657
+ foreach(array_diff_key($input, $this->settings) as $setting => $value)
658
  {
659
  $temp .= '<br />' . $setting;
660
  }
661
+ $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');
662
  }
663
  add_action('admin_notices', array($this, 'messages'));
664
  }
665
+ /**
666
+ * Retrieves the settings from database and exports as JSON
667
+ */
668
+ function settings_export()
669
+ {
670
+ //TODO: implement this, see #239
671
+ }
672
+ /**
673
+ * Imports JSON settings into database
674
+ */
675
+ function settings_inport()
676
+ {
677
+ //TODO: implement this, see #239
678
+ }
679
  /**
680
  * Exports a XML options document
681
  */
775
  //Commit the loaded options to the database
776
  $this->update_option($this->unique_prefix . '_options', $this->opt);
777
  //Everything was successful, let the user know
778
+ $this->messages[] = new message(esc_html__('Settings successfully imported from the uploaded file.', $this->identifier)
779
  . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier)), 'success');
780
  }
781
  else
782
  {
783
  //Throw an error since we could not load the file for various reasons
784
+ $this->messages[] = new message(esc_html__('Importing settings from file failed.', $this->identifier), 'error');
785
  }
786
  //Reset to the default error handler after we're done
787
  restore_error_handler();
798
  //Set the backup options in the DB to the current options
799
  $this->opts_backup();
800
  //Load in the hard coded default option values
801
+ $this->update_option($this->unique_prefix . '_options', adminKit::settings_to_opts($this->settings));
802
  //Reset successful, let the user know
803
+ $this->messages[] = new message(esc_html__('Settings successfully reset to the default values.', $this->identifier)
804
  . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier)), 'success');
805
  add_action('admin_notices', array($this, 'messages'));
806
  }
818
  //Set the backup options to the undone options
819
  $this->update_option($this->unique_prefix . '_options_bk', $opt);
820
  //Send the success/undo message
821
+ $this->messages[] = new message(esc_html__('Settings successfully undid the last operation.', $this->identifier)
822
  . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier)), 'success');
823
  add_action('admin_notices', array($this, 'messages'));
824
  }
838
  }
839
  /**
840
  * Forces a database settings upgrade
841
+ *
842
+ * FIXME: seems there is a lot of very similar code in install
843
  */
844
  function opts_upgrade_wrapper()
845
  {
856
  //Store the options
857
  $this->update_option($this->unique_prefix . '_options', $this->opt);
858
  //Send the success message
859
+ $this->messages[] = new message(esc_html__('Settings successfully migrated.', $this->identifier), 'success');
860
  }
861
  else
862
  {
863
  //Run the install script
864
  $this->install();
865
  //Send the success message
866
+ $this->messages[] = new message(esc_html__('Default settings successfully installed.', $this->identifier), 'success');
867
  }
868
  add_action('admin_notices', array($this, 'messages'));
869
  }
887
  //Grab the submitted UID
888
  $uid = esc_attr($_POST['uid']);
889
  //Create a dummy message, with the discovered UID
890
+ $message = new message('', '', true, $uid);
891
  //Dismiss the message
892
  $message->dismiss();
893
  wp_die();
957
  * Returns a valid xHTML element ID
958
  *
959
  * @param object $option
960
+ *
961
+ * @deprecated 7.0.0
962
  */
963
  static public function get_valid_id($option)
964
  {
965
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::get_valid_id');
966
  if(is_numeric($option[0]))
967
  {
968
  return 'p' . $option;
997
  * This will output a well formed hidden option
998
  *
999
  * @param string $option
1000
+ *
1001
+ * @deprecated 7.0.0
1002
  */
1003
  function input_hidden($option)
1004
  {
1005
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_hidden');
1006
+ $opt_id = adminKit::get_valid_id($option);
1007
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1008
  printf('<input type="hidden" name="%1$s" id="%2$s" value="%3$s" />', esc_attr($opt_name), esc_attr($opt_id), esc_attr($this->opt[$option]));
1009
  }
1012
  *
1013
  * @param string $opt_id
1014
  * @param string $label
1015
+ *
1016
+ * @deprecated 7.0.0
1017
  */
1018
  function label($opt_id, $label)
1019
  {
1020
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::label');
1021
  printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);
1022
  }
1023
  /**
1028
  * @param string $class (optional)
1029
  * @param bool $disable (optional)
1030
  * @param string $description (optional)
1031
+ *
1032
+ * @deprecated 7.0.0
1033
  */
1034
  function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '')
1035
  {
1036
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_text');
1037
+ $opt_id = adminKit::get_valid_id($option);
1038
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1039
  if($disable)
1040
  {
1063
  * @param int|string $min (optional)
1064
  * @param int|string $max (optional)
1065
  * @param int|string $step (optional)
1066
+ *
1067
+ * @deprecated 7.0.0
1068
  */
1069
  function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')
1070
  {
1071
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_number');
1072
+ $opt_id = adminKit::get_valid_id($option);
1073
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1074
  $extras = '';
1075
  if($min !== '')
1108
  * @param string $rows (optional)
1109
  * @param bool $disable (optional)
1110
  * @param string $description (optional)
1111
+ *
1112
+ * @deprecated 7.0.0
1113
  */
1114
  function textbox($label, $option, $height = '3', $disable = false, $description = '', $class = '')
1115
  {
1116
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::textbox');
1117
+ $opt_id = adminKit::get_valid_id($option);
1118
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1119
  $class .= ' large-text';
1120
  if($disable)
1141
  * @param string $rows (optional)
1142
  * @param bool $disable (optional)
1143
  * @param string $description (optional)
1144
+ *
1145
+ * @deprecated 7.0.0
1146
  */
1147
  function tinymce($label, $option, $height = '3', $disable = false, $description = '')
1148
  {
1149
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::tinymce');
1150
+ $opt_id = adminKit::get_valid_id($option);
1151
  $class = 'mtekk_mce';
1152
  if($disable)
1153
  {
1174
  * @param bool $disable (optional)
1175
  * @param string $description (optional)
1176
  * @param string $class (optional)
1177
+ *
1178
+ * @deprecated 7.0.0
1179
  */
1180
  function input_check($label, $option, $instruction, $disable = false, $description = '', $class = '')
1181
  {
1182
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_check');
1183
+ $opt_id = adminKit::get_valid_id($option);
1184
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1185
  if($disable)
1186
  {
1209
  * @param string $instruction
1210
  * @param object $disable (optional)
1211
  * @param string $class (optional)
1212
+ *
1213
+ * @deprecated 7.0.0
1214
  */
1215
  function input_radio($option, $value, $instruction, $disable = false, $class = '')
1216
  {
1217
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_radio');
1218
+ $opt_id = adminKit::get_valid_id($option);
1219
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1220
  $class .= ' togx';
1221
  if($disable)
1239
  * @param string $description (optional)
1240
  * @param array $titles (optional) The array of titiles for the options, if they should be different from the values
1241
  * @param string $class (optional) Extra class to apply to the elements
1242
+ *
1243
+ * @deprecated 7.0.0
1244
  */
1245
  function input_select($label, $option, $values, $disable = false, $description = '', $titles = false, $class = '')
1246
  {
1247
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::input_select');
1248
  //If we don't have titles passed in, we'll use option names as values
1249
  if(!$titles)
1250
  {
1251
  $titles = $values;
1252
  }
1253
+ $opt_id = adminKit::get_valid_id($option);
1254
  $opt_name = $this->unique_prefix . '_options[' . $option . ']';
1255
  if($disable)
1256
  {
1277
  * @param array $exclude(optional) array of names in $options array to be excluded
1278
  *
1279
  * @return string The assembled HTML for the select options
1280
+ *
1281
+ * @deprecated 7.0.0
1282
  */
1283
  function select_options($optionname, $options, $values, $exclude = array())
1284
  {
1285
+ _deprecated_function( __FUNCTION__, '7.0', '\mtekk\adminKit\form::select_options');
1286
  $options_html = '';
1287
  $value = $this->opt[$optionname];
1288
  //Now do the rest
includes/adminKit/class-mtekk_adminkit_form.php ADDED
@@ -0,0 +1,394 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit;
20
+ use mtekk\adminKit\setting\setting as setting;
21
+ require_once( __DIR__ . '/../block_direct_access.php');
22
+ //Include setting interface
23
+ if(!interface_exists('\mtekk\adminKit\setting\setting'))
24
+ {
25
+ require_once( __DIR__ . '/interface-mtekk_adminkit_setting.php');
26
+ }
27
+ class form
28
+ {
29
+ const version = '1.0.0';
30
+ protected $unique_prefix;
31
+ /**
32
+ * Default constructor function
33
+ *
34
+ * @param string $unique_prefix
35
+ */
36
+ public function __construct($unique_prefix)
37
+ {
38
+ $this->unique_prefix = $unique_prefix;
39
+ }
40
+ /**
41
+ * Returns a valid xHTML element ID
42
+ *
43
+ * @param object $option
44
+ */
45
+ static public function get_valid_id($option)
46
+ {
47
+ if(is_numeric($option[0]))
48
+ {
49
+ return 'p' . $option;
50
+ }
51
+ else
52
+ {
53
+ return $option;
54
+ }
55
+ }
56
+ /**
57
+ * This will output a well formed hidden option
58
+ *
59
+ * @param string $option
60
+ */
61
+ public function input_hidden(setting $option)
62
+ {
63
+ $opt_id = form::get_valid_id($option->get_name());
64
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';
65
+ printf('<input type="hidden" name="%1$s" id="%2$s" value="%3$s" />',
66
+ esc_attr($opt_name),
67
+ esc_attr($opt_id),
68
+ esc_attr($option->get_value()));
69
+ }
70
+ /**
71
+ * This will output a well formed option label
72
+ *
73
+ * @param string $opt_id
74
+ * @param string $label
75
+ */
76
+ public function label($opt_id, $label)
77
+ {
78
+ printf('<label for="%1$s">%2$s</label>', esc_attr($opt_id), $label);
79
+ }
80
+ /**
81
+ * This will output a well formed table row for a text input
82
+ *
83
+ * @param setting $option
84
+ * @param string $class (optional)
85
+ * @param bool $disable (optional)
86
+ * @param string $description (optional)
87
+ */
88
+ public function input_text(setting $option, $class = 'regular-text', $disable = false, $description = '')
89
+ {
90
+ $opt_id = form::get_valid_id($option->get_name());
91
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';?>
92
+ <tr valign="top">
93
+ <th scope="row">
94
+ <?php $this->label($opt_id, $option->get_title());?>
95
+ </th>
96
+ <td>
97
+ <?php
98
+ if($disable)
99
+ {
100
+ $this->input_hidden($option);
101
+ $class .= ' disabled';
102
+ }
103
+ printf('<input type="text" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s/><br />',
104
+ esc_attr($opt_name),
105
+ esc_attr($opt_id),
106
+ esc_attr($option->get_value()),
107
+ esc_attr($class),
108
+ disabled($disable, true, false));
109
+ if($description !== '')
110
+ {
111
+ printf('<p class="description">%s</p>', $description);
112
+ }?>
113
+ </td>
114
+ </tr>
115
+ <?php
116
+ }
117
+ /**
118
+ * This will output a well formed table row for a HTML5 number input
119
+ *
120
+ * @param setting $option
121
+ * @param string $class (optional)
122
+ * @param bool $disable (optional)
123
+ * @param string $description (optional)
124
+ * @param int|string $min (optional)
125
+ * @param int|string $max (optional)
126
+ * @param int|string $step (optional)
127
+ */
128
+ public function input_number(setting $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')
129
+ {
130
+ $opt_id = form::get_valid_id($option->get_name());
131
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';
132
+ $extras = '';
133
+ if($min !== '')
134
+ {
135
+ $extras .= 'min="' . esc_attr($min) . '" ';
136
+ }
137
+ if($max !== '')
138
+ {
139
+ $extras .= 'max="' . esc_attr($max) . '" ';
140
+ }
141
+ if($step !== '')
142
+ {
143
+ $extras .= 'step="' . esc_attr($step) . '" ';
144
+ }?>
145
+ <tr valign="top">
146
+ <th scope="row">
147
+ <?php $this->label($opt_id, $option->get_title());?>
148
+ </th>
149
+ <td>
150
+ <?php
151
+ if($disable)
152
+ {
153
+ $this->input_hidden($option);
154
+ $class .= ' disabled';
155
+ }
156
+ printf('<input type="number" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %6$s%5$s/><br />',
157
+ esc_attr($opt_name),
158
+ esc_attr($opt_id),
159
+ esc_attr($option->get_value()),
160
+ esc_attr($class),
161
+ disabled($disable, true, false),
162
+ $extras);
163
+ if($description !== '')
164
+ {
165
+ printf('<p class="description">%s</p>', $description);
166
+ }?>
167
+ </td>
168
+ </tr>
169
+ <?php
170
+ }
171
+ /**
172
+ * This will output a well formed textbox
173
+ *
174
+ * @param setting $option
175
+ * @param string $rows (optional)
176
+ * @param bool $disable (optional)
177
+ * @param string $description (optional)
178
+ */
179
+ public function textbox(setting $option, $height = '3', $disable = false, $description = '', $class = '')
180
+ {
181
+ $opt_id = form::get_valid_id($option->get_name());
182
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';
183
+ $class .= ' large-text';?>
184
+ <tr valign="top">
185
+ <th scope="row">
186
+ <?php $this->label($opt_id, $option->get_title());?>
187
+ </th>
188
+ <td>
189
+ <?php
190
+ if($disable)
191
+ {
192
+ $this->input_hidden($option);
193
+ $class .= ' disabled';
194
+ }
195
+ printf('<textarea rows="%6$s" name="%1$s" id="%2$s" class="%4$s" %5$s/>%3$s</textarea><br />',
196
+ esc_attr($opt_name),
197
+ esc_attr($opt_id),
198
+ esc_textarea($option->get_value()),
199
+ esc_attr($class),
200
+ disabled($disable, true, false),
201
+ esc_attr($height));
202
+ if($description !== '')
203
+ {
204
+ printf('<p class="description">%s</p>', $description);
205
+ }?>
206
+ </td>
207
+ </tr>
208
+ <?php
209
+ }
210
+ /**
211
+ * This will output a well formed tiny mce ready textbox
212
+ *
213
+ * @param setting $option
214
+ * @param string $rows (optional)
215
+ * @param bool $disable (optional)
216
+ * @param string $description (optional)
217
+ */
218
+ public function tinymce(setting $option, $height = '3', $disable = false, $description = '')
219
+ {
220
+ $opt_id = form::get_valid_id($option->get_name());
221
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';
222
+ $class = 'mtekk_mce';?>
223
+ <tr valign="top">
224
+ <th scope="row">
225
+ <?php $this->label($opt_id, $option->get_title());?>
226
+ </th>
227
+ <td>
228
+ <?php
229
+ if($disable)
230
+ {
231
+ $this->input_hidden($option);
232
+ $class .= ' disabled';
233
+ }
234
+ printf('<textarea rows="%6$s" name="%1$s" id="%2$s" class="%4$s" %5$s/>%3$s</textarea><br />',
235
+ esc_attr($opt_name),
236
+ esc_attr($opt_id),
237
+ esc_textarea($option->get_value()),
238
+ esc_attr($class),
239
+ disabled($disable, true, false),
240
+ esc_attr($height));
241
+ if($description !== '')
242
+ {
243
+ printf('<p class="description">%s</p>', $description);
244
+ }?>
245
+ </td>
246
+ </tr>
247
+ <?php
248
+ }
249
+ /**
250
+ * This will output a well formed table row for a checkbox input
251
+ *
252
+ * @param setting $option
253
+ * @param string $instruction
254
+ * @param bool $disable (optional)
255
+ * @param string $description (optional)
256
+ * @param string $class (optional)
257
+ */
258
+ public function input_check(setting $option, $instruction, $disable = false, $description = '', $class = '')
259
+ {
260
+ $opt_id = form::get_valid_id($option->get_name());
261
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';?>
262
+ <tr valign="top">
263
+ <th scope="row">
264
+ <?php echo esc_html($option->get_title()); ?>
265
+ </th>
266
+ <td>
267
+ <label for="<?php echo esc_attr( $opt_id ); ?>">
268
+ <?php
269
+ if($disable)
270
+ {
271
+ $this->input_hidden($option);
272
+ $class .= ' disabled';
273
+ }
274
+ printf('<input type="checkbox" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s %6$s/>',
275
+ esc_attr($opt_name),
276
+ esc_attr($opt_id),
277
+ esc_attr($option->get_value()),
278
+ esc_attr($class),
279
+ disabled($disable, true, false),
280
+ checked($option->get_value(), true, false));
281
+ echo $instruction;?>
282
+ </label><br />
283
+ <?php
284
+ if($description !== '')
285
+ {
286
+ printf('<p class="description">%s</p>', $description);
287
+ }?>
288
+ </td>
289
+ </tr>
290
+ <?php
291
+ }
292
+ /**
293
+ * This will output a singular radio type form input field
294
+ *
295
+ * @param setting $option
296
+ * @param string $value
297
+ * @param string $instruction
298
+ * @param object $disable (optional)
299
+ * @param string $class (optional)
300
+ */
301
+ public function input_radio(setting $option, $value, $instruction, $disable = false, $class = '')
302
+ {
303
+ $opt_id = form::get_valid_id($option->get_name());
304
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';
305
+ $class .= ' togx';?>
306
+ <label>
307
+ <?php
308
+ if($disable)
309
+ {
310
+ $this->input_hidden($option);
311
+ $class .= ' disabled';
312
+ }
313
+ printf('<input type="radio" name="%1$s" id="%2$s" value="%3$s" class="%4$s" %5$s %6$s/>',
314
+ esc_attr($opt_name),
315
+ esc_attr($opt_id),
316
+ esc_attr($value),
317
+ esc_attr($class),
318
+ disabled($disable, true, false),
319
+ checked($value, $option->get_value(), false));
320
+ echo $instruction; ?>
321
+ </label><br/>
322
+ <?php
323
+ }
324
+ /**
325
+ * This will output a well formed table row for a select input
326
+ *
327
+ * @param setting $option
328
+ * @param array $values
329
+ * @param bool $disable (optional)
330
+ * @param string $description (optional)
331
+ * @param array $titles (optional) The array of titiles for the options, if they should be different from the values
332
+ * @param string $class (optional) Extra class to apply to the elements
333
+ */
334
+ public function input_select(setting $option, $values, $disable = false, $description = '', $titles = false, $class = '')
335
+ {
336
+ //If we don't have titles passed in, we'll use option names as values
337
+ if(!$titles)
338
+ {
339
+ $titles = $values;
340
+ }
341
+ $opt_id = form::get_valid_id($option->get_name());
342
+ $opt_name = $this->unique_prefix . '_options[' . $option->get_opt_name(). ']';?>
343
+ <tr valign="top">
344
+ <th scope="row">
345
+ <?php $this->label($opt_id, $option->get_title());?>
346
+ </th>
347
+ <td>
348
+ <?php
349
+ if($disable)
350
+ {
351
+ $this->input_hidden($option);
352
+ $class .= ' disabled';
353
+ }
354
+ printf('<select name="%1$s" id="%2$s" class="%4$s" %5$s>%3$s</select><br />',
355
+ esc_attr($opt_name),
356
+ esc_attr($opt_id),
357
+ $this->select_options($option->get_value(), $titles, $values),
358
+ esc_attr($class),
359
+ disabled($disable, true, false));
360
+ if($description !== '')
361
+ {
362
+ printf('<p class="description">%s</p>', $description);
363
+ }?>
364
+ </td>
365
+ </tr>
366
+ <?php
367
+ }
368
+ /**
369
+ * Generates <seclect> block based off of passed in options array
370
+ *
371
+ * @param string $current_value current value of option
372
+ * @param array $options array of names of options that can be selected
373
+ * @param array $values array of the values of the options that can be selected
374
+ * @param array $exclude(optional) array of names in $options array to be excluded
375
+ *
376
+ * @return string The assembled HTML for the select options
377
+ */
378
+ public function select_options($current_value, $options, $values, $exclude = array())
379
+ {
380
+ $options_html = '';
381
+ //Now do the rest
382
+ foreach($options as $key => $option)
383
+ {
384
+ if(!in_array($option, $exclude))
385
+ {
386
+ $options_html .= sprintf('<option value="%1$s" %2$s>%3$s</option>',
387
+ esc_attr($values[$key]),
388
+ selected($current_value, $values[$key], false),
389
+ $option);
390
+ }
391
+ }
392
+ return $options_html;
393
+ }
394
+ }
includes/{class.mtekk_adminkit_message.php → adminKit/class-mtekk_adminkit_message.php} RENAMED
@@ -16,8 +16,9 @@
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
  */
19
- require_once(dirname(__FILE__) . '/block_direct_access.php');
20
- class mtekk_adminKit_message
 
21
  {
22
  const version = '1.0.0';
23
  protected $type = '';
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
  */
19
+ namespace mtekk\adminKit;
20
+ require_once( __DIR__ . '/../block_direct_access.php');
21
+ class message
22
  {
23
  const version = '1.0.0';
24
  protected $type = '';
includes/{class.mtekk_adminkit_uninstaller.php → adminKit/class-mtekk_adminkit_uninstaller.php} RENAMED
@@ -16,7 +16,7 @@
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
  */
19
- require_once(dirname(__FILE__) . '/block_direct_access.php');
20
  /**
21
  * Breadcrumb NavXT abstract plugin uninstaller class
22
  *
@@ -34,7 +34,7 @@ abstract class mtekk_adminKit_uninstaller
34
  */
35
  protected function _get_plugin_path()
36
  {
37
- return sprintf('%s/%s', dirname(dirname(__FILE__)), $this->plugin_basename);
38
  }
39
 
40
  /**
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
  */
19
+ require_once( __DIR__ . '/../block_direct_access.php');
20
  /**
21
  * Breadcrumb NavXT abstract plugin uninstaller class
22
  *
34
  */
35
  protected function _get_plugin_path()
36
  {
37
+ return sprintf('%s/%s', dirname(dirname(__DIR__)), $this->plugin_basename);
38
  }
39
 
40
  /**
includes/adminKit/setting/class-mtekk_adminkit_setting_absint.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_absint extends setting_base
27
+ {
28
+ /**
29
+ * Default constructor function
30
+ *
31
+ * @param string $title The display title of the setting
32
+ */
33
+ public function __construct(string $name, int $value, string $title, bool $allow_empty = false, bool $deprecated = false)
34
+ {
35
+ $this->name = $name;
36
+ $this->value = $value;
37
+ $this->title = $title;
38
+ $this->allow_empty = $allow_empty;
39
+ $this->deprecated = $deprecated;
40
+ }
41
+ /**
42
+ *
43
+ */
44
+ public function validate($new_value)
45
+ {
46
+ return absint($new_value);
47
+ }
48
+ /**
49
+ *
50
+ * {@inheritDoc}
51
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
52
+ */
53
+ public function get_opt_name()
54
+ {
55
+ return 'a' . $this->get_name();
56
+ }
57
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_base.php ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting interface
22
+ if(!interface_exists('mtekk_adminKit_setting'))
23
+ {
24
+ require_once( __DIR__ . '/interface-mtekk_adminkit_setting.php');
25
+ }
26
+ abstract class setting_base implements setting
27
+ {
28
+ const version = '1.0.0';
29
+ protected $name = '';
30
+ protected $value = '';
31
+ protected $title = '';
32
+ protected $allow_empty = false;
33
+ protected $deprecated = false;
34
+ public function is_deprecated()
35
+ {
36
+ return $this->deprecated;
37
+ }
38
+ public function set_deprecated($deprecated)
39
+ {
40
+ $this->deprecated = $deprecated;
41
+ }
42
+ public function get_value()
43
+ {
44
+ return $this->value;
45
+ }
46
+ public function set_value($new_value)
47
+ {
48
+ $this->value = $new_value;
49
+ }
50
+ public function get_title()
51
+ {
52
+ return $this->title;
53
+ }
54
+ public function get_name()
55
+ {
56
+ return $this->name;
57
+ }
58
+ public function get_allow_empty()
59
+ {
60
+ return $this->allow_empty;
61
+ }
62
+ public function set_allow_empty($allow_empty)
63
+ {
64
+ $this->allow_empty = $allow_empty;
65
+ }
66
+ /**
67
+ * Basic updateFromFormInput method
68
+ *
69
+ * {@inheritDoc}
70
+ * @see mtekk\adminKit\setting::maybe_update_from_form_input()
71
+ */
72
+ public function maybe_update_from_form_input($input)
73
+ {
74
+ if(isset($input[$this->get_opt_name()]))
75
+ {
76
+ $this->set_value($this->validate($input[$this->get_opt_name()]));
77
+ }
78
+ }
79
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_bool.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('mtekk_adminKit_setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_bool extends setting_base
27
+ {
28
+ /**
29
+ * Default constructor function
30
+ *
31
+ * @param string $title The display title of the setting
32
+ */
33
+ public function __construct(string $name, bool $value, string $title, bool $allow_empty = false, bool $deprecated = false)
34
+ {
35
+ $this->name = $name;
36
+ $this->value = $value;
37
+ $this->title = $title;
38
+ $this->allow_empty = $allow_empty;
39
+ $this->deprecated = $deprecated;
40
+ }
41
+ /**
42
+ *
43
+ */
44
+ public function validate($new_value)
45
+ {
46
+ return (bool) $new_value;
47
+ }
48
+ /**
49
+ *
50
+ * {@inheritDoc}
51
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
52
+ */
53
+ public function get_opt_name()
54
+ {
55
+ return 'b' . $this->get_name();
56
+ }
57
+ /**
58
+ *
59
+ * {@inheritDoc}
60
+ * @see mtekk_adminKit_setting::updateFromFormInput()
61
+ */
62
+ public function maybe_update_from_form_input($input)
63
+ {
64
+ $this->set_value($this->validate(isset($input[$this->get_opt_name()])));
65
+ }
66
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_enum.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('mtekk_adminKit_setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_enum extends setting_base
27
+ {
28
+ protected $allowed_vals = array();
29
+ /**
30
+ * Default constructor function
31
+ *
32
+ * @param string $title The display title of the setting
33
+ */
34
+ public function __construct(string $name, string $value, string $title, bool $allow_empty = false, bool $deprecated = false, array $allowed_vals = array())
35
+ {
36
+ $this->name = $name;
37
+ $this->value = $value;
38
+ $this->title = $title;
39
+ $this->deprecated = $deprecated;
40
+ $this->allow_empty = $allow_empty;
41
+ $this->allowed_vals= $allowed_vals;
42
+ }
43
+ /**
44
+ * Validates the new value against the allowed values for this setting
45
+ *
46
+ * {@inheritDoc}
47
+ * @see mtekk_adminKit_setting::validate()
48
+ */
49
+ public function validate($new_value)
50
+ {
51
+ if(in_array($new_value, $this->allowed_vals))
52
+ {
53
+ return $new_value;
54
+ }
55
+ else
56
+ {
57
+ return $this->value;
58
+ }
59
+ }
60
+ /**
61
+ *
62
+ * {@inheritDoc}
63
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
64
+ */
65
+ public function get_opt_name()
66
+ {
67
+ return 'E' . $this->get_name();
68
+ }
69
+ /**
70
+ * Setter for the allowed values array
71
+ *
72
+ * @param array $allowed_vals Array of allowed values
73
+ */
74
+ public function set_allowed_vals(array $allowed_vals)
75
+ {
76
+ $this->allowed_vals = $allowed_vals;
77
+ }
78
+ /**
79
+ * Getter of the allowed values array
80
+ *
81
+ * @return array Allowed values used in validation of the setting
82
+ */
83
+ public function get_allowed_vals()
84
+ {
85
+ return $this->allowed_vals;
86
+ }
87
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_float.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_float extends setting_base
27
+ {
28
+ /**
29
+ * Default constructor function
30
+ *
31
+ * @param string $title The display title of the setting
32
+ */
33
+ public function __construct(string $name, float $value, string $title, bool $allow_empty = false, bool $deprecated = false)
34
+ {
35
+ $this->name = $name;
36
+ $this->value = $value;
37
+ $this->title = $title;
38
+ $this->allow_empty = $allow_empty;
39
+ $this->deprecated = $deprecated;
40
+ }
41
+ /**
42
+ *
43
+ */
44
+ public function validate($new_value)
45
+ {
46
+ return (float) $new_value;
47
+ }
48
+ /**
49
+ *
50
+ * {@inheritDoc}
51
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
52
+ */
53
+ public function get_opt_name()
54
+ {
55
+ return 'f' . $this->get_name();
56
+ }
57
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_html.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_html extends setting_base
27
+ {
28
+ /**
29
+ * Default constructor function
30
+ *
31
+ * @param string $title The display title of the setting
32
+ */
33
+ public function __construct(string $name, string $value, string $title, bool $allow_empty = false, bool $deprecated = false)
34
+ {
35
+ $this->name = $name;
36
+ $this->value = $value;
37
+ $this->title = $title;
38
+ $this->allow_empty = $allow_empty;
39
+ $this->deprecated = $deprecated;
40
+ }
41
+ /**
42
+ *
43
+ */
44
+ public function validate($new_value)
45
+ {
46
+ if(!$this->allow_empty && $new_value === '')
47
+ {
48
+ return $this->value;
49
+ }
50
+ return wp_kses(stripslashes($new_value), apply_filters('mtekk_adminkit_allowed_html', wp_kses_allowed_html('post')));
51
+ }
52
+ /**
53
+ *
54
+ * {@inheritDoc}
55
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
56
+ */
57
+ public function get_opt_name()
58
+ {
59
+ if($this->allow_empty)
60
+ {
61
+ $type = 'h';
62
+ }
63
+ else
64
+ {
65
+ $type = 'H';
66
+ }
67
+ return $type . $this->get_name();
68
+ }
69
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_int.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_int extends setting_base
27
+ {
28
+ /**
29
+ * Default constructor function
30
+ *
31
+ * @param string $title The display title of the setting
32
+ */
33
+ public function __construct(string $name, int $value, string $title, bool $allow_empty = false, bool $deprecated = false)
34
+ {
35
+ $this->name = $name;
36
+ $this->value = $value;
37
+ $this->title = $title;
38
+ $this->allow_empty = $allow_empty;
39
+ $this->deprecated = $deprecated;
40
+ }
41
+ /**
42
+ *
43
+ */
44
+ public function validate($new_value)
45
+ {
46
+ return (int) $new_value;
47
+ }
48
+ /**
49
+ *
50
+ * {@inheritDoc}
51
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
52
+ */
53
+ public function get_opt_name()
54
+ {
55
+ return 'i' . $this->get_name();
56
+ }
57
+ }
includes/adminKit/setting/class-mtekk_adminkit_setting_string.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ //Include setting base class
22
+ if(!class_exists('mtekk_adminKit_setting_base'))
23
+ {
24
+ require_once( __DIR__ . '/class-mtekk_adminkit_setting_base.php');
25
+ }
26
+ class setting_string extends setting_base
27
+ {
28
+ /**
29
+ * Default constructor function
30
+ *
31
+ * @param string $title The display title of the setting
32
+ */
33
+ public function __construct(string $name, string $value, string $title, bool $allow_empty = false, bool $deprecated = false)
34
+ {
35
+ $this->name = $name;
36
+ $this->value = $value;
37
+ $this->title = $title;
38
+ $this->allow_empty = $allow_empty;
39
+ $this->deprecated = $deprecated;
40
+ }
41
+ /**
42
+ *
43
+ */
44
+ public function validate($new_value)
45
+ {
46
+ if(!$this->allow_empty && $new_value === '')
47
+ {
48
+ return $this->value;
49
+ }
50
+ return esc_html($new_value);
51
+ }
52
+ /**
53
+ *
54
+ * {@inheritDoc}
55
+ * @see \mtekk\adminKit\setting\setting::get_opt_name()
56
+ */
57
+ public function get_opt_name()
58
+ {
59
+ if($this->allow_empty)
60
+ {
61
+ $type = 's';
62
+ }
63
+ else
64
+ {
65
+ $type = 'S';
66
+ }
67
+ return $type . $this->get_name();
68
+ }
69
+ }
includes/adminKit/setting/interface-mtekk_adminkit_setting.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2020-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ namespace mtekk\adminKit\setting;
20
+ require_once( __DIR__ . '/../../block_direct_access.php');
21
+ interface setting
22
+ {
23
+ /**
24
+ * Validation method
25
+ *
26
+ * @param unknown $new_value new setting value to validate
27
+ * @return the validated version of the setting (may be old/current value if new value was invalid)
28
+ */
29
+ public function validate($new_value);
30
+ public function is_deprecated();
31
+ public function set_deprecated($deprecated);
32
+ public function get_value();
33
+ public function set_value($new_value);
34
+ public function get_title();
35
+ public function get_name();
36
+ public function get_allow_empty();
37
+ public function set_allow_empty($allow_empty);
38
+ /**
39
+ * @return string The 'option' name for this setting, a combination of the type and name
40
+ */
41
+ public function get_opt_name();
42
+ /**
43
+ * Update from form values method
44
+ *
45
+ * @param array $input Array of new values from well formatted form POST request
46
+ */
47
+ public function maybe_update_from_form_input($input);
48
+ //public function render(); //This is a future item we'll add, maybe
49
+ }
options_upgrade.php ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright 2015-2021 John Havlik (email : john.havlik@mtekk.us)
4
+
5
+ This program is free software; you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation; either version 2 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program; if not, write to the Free Software
17
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+ require_once(dirname(__FILE__) . '/includes/block_direct_access.php');
20
+ //Do a PHP version check, require 5.3 or newer
21
+ if(version_compare(phpversion(), '5.3.0', '<'))
22
+ {
23
+ //Only purpose of this function is to echo out the PHP version error
24
+ function bcn_phpold()
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');
27
+ }
28
+ //If we are in the admin, let's print a warning then return
29
+ if(is_admin())
30
+ {
31
+ add_action('admin_notices', 'bcn_phpold');
32
+ }
33
+ return;
34
+ }
35
+ //FIXME: this seems to be all sorts of garbage that needs fixing
36
+ function bcn_options_upgrade_handler(&$opts, $version, $defaults)
37
+ {
38
+ //Upgrading to 3.8.1
39
+ if(version_compare($version, '3.8.1', '<'))
40
+ {
41
+ $opts['post_page_root'] = get_option('page_on_front');
42
+ $opts['post_post_root'] = get_option('page_for_posts');
43
+ }
44
+ //Upgrading to 4.0
45
+ if(version_compare($version, '4.0.0', '<'))
46
+ {
47
+ //Only migrate if we haven't migrated yet
48
+ if(isset($opts['current_item_linked']))
49
+ {
50
+ //Loop through the old options, migrate some of them
51
+ foreach($opts as $option => $value)
52
+ {
53
+ //Handle all of our boolean options first, they're real easy, just add a 'b'
54
+ if(strpos($option, 'display') > 0 || $option == 'current_item_linked')
55
+ {
56
+ $defaults['b' . $option] = $value;
57
+ }
58
+ //Handle migration of anchor templates to the templates
59
+ else if(strpos($option, 'anchor') > 0)
60
+ {
61
+ $parts = explode('_', $option);
62
+ //Do excess slash removal sanitation
63
+ $defaults['H' . $parts[0] . '_template'] = $value . '%htitle%</a>';
64
+ }
65
+ //Handle our abs integers
66
+ else if($option == 'max_title_length' || $option == 'post_post_root' || $option == 'post_page_root')
67
+ {
68
+ $opts['a' . $option] = $value;
69
+ }
70
+ //Now everything else, minus prefix and suffix
71
+ else if(strpos($option, 'prefix') === false && strpos($option, 'suffix') === false)
72
+ {
73
+ $defaults['S' . $option] = $value;
74
+ }
75
+ }
76
+ }
77
+ //Add in the new settings for CPTs introduced in 4.0
78
+ foreach($GLOBALS['wp_post_types'] as $post_type)
79
+ {
80
+ //We only want custom post types
81
+ if(!$post_type->_builtin)
82
+ {
83
+ //Add in the archive_display option
84
+ $defaults['bpost_' . $post_type->name . '_archive_display'] = $post_type->has_archive;
85
+ }
86
+ }
87
+ $opts = $defaults;
88
+ }
89
+ if(version_compare($version, '4.0.1', '<'))
90
+ {
91
+ if(isset($opts['Hcurrent_item_template_no_anchor']))
92
+ {
93
+ unset($opts['Hcurrent_item_template_no_anchor']);
94
+ }
95
+ if(isset($opts['Hcurrent_item_template']))
96
+ {
97
+ unset($opts['Hcurrent_item_template']);
98
+ }
99
+ }
100
+ //Upgrading to 4.3.0
101
+ if(version_compare($version, '4.3.0', '<'))
102
+ {
103
+ //Removed home_title
104
+ if(isset($opts['Shome_title']))
105
+ {
106
+ unset($opts['Shome_title']);
107
+ }
108
+ //Removed mainsite_title
109
+ if(isset($opts['Smainsite_title']))
110
+ {
111
+ unset($opts['Smainsite_title']);
112
+ }
113
+ }
114
+ //Upgrading to 5.1.0
115
+ if(version_compare($version, '5.1.0', '<'))
116
+ {
117
+ foreach($GLOBALS['wp_taxonomies'] as $taxonomy)
118
+ {
119
+ //If we have the old options style for it, update
120
+ if($taxonomy->name !== 'post_format' && isset($opts['H' . $taxonomy->name . '_template']))
121
+ {
122
+ //Migrate to the new setting name
123
+ $opts['Htax_' . $taxonomy->name . '_template'] = $opts['H' . $taxonomy->name . '_template'];
124
+ $opts['Htax_' . $taxonomy->name . '_template_no_anchor'] = $opts['H' . $taxonomy->name . '_template_no_anchor'];
125
+ //Clean up old settings
126
+ unset($opts['H' . $taxonomy->name . '_template']);
127
+ unset($opts['H' . $taxonomy->name . '_template_no_anchor']);
128
+ }
129
+ }
130
+ }
131
+ //Upgrading to 5.4.0
132
+ if(version_compare($version, '5.4.0', '<'))
133
+ {
134
+ //Migrate users to schema.org breadcrumbs for author and search if still on the defaults for posts
135
+ if($opts['Hpost_post_template'] === bcn_breadcrumb::get_default_template() && $opts['Hpost_post_template_no_anchor'] === bcn_breadcrumb::default_template_no_anchor)
136
+ {
137
+ if($opts['Hpaged_template'] === 'Page %htitle%')
138
+ {
139
+ $opts['Hpaged_template'] = $defaults['Hpaged_template'];
140
+ }
141
+ if($opts['Hsearch_template'] === 'Search results for &#39;<a title="Go to the first page of search results for %title%." href="%link%" class="%type%">%htitle%</a>&#39;' || $opts['Hsearch_template'] === 'Search results for &#039;<a title="Go to the first page of search results for %title%." href="%link%" class="%type%">%htitle%</a>&#039;')
142
+ {
143
+ $opts['Hsearch_template'] = $defaults['Hsearch_template'];
144
+ }
145
+ if($opts['Hsearch_template_no_anchor'] === 'Search results for &#39;%htitle%&#39;' || $opts['Hsearch_template_no_anchor'] === 'Search results for &#039;%htitle%&#039;')
146
+ {
147
+ $opts['Hsearch_template_no_anchor'] = $defaults['Hsearch_template_no_anchor'];
148
+ }
149
+ if($opts['Hauthor_template'] === 'Articles by: <a title="Go to the first page of posts by %title%." href="%link%" class="%type%">%htitle%</a>')
150
+ {
151
+ $opts['Hauthor_template'] = $defaults['Hauthor_template'];
152
+ }
153
+ if($opts['Hauthor_template_no_anchor'] === 'Articles by: %htitle%')
154
+ {
155
+ $opts['Hauthor_template_no_anchor'] = $defaults['Hauthor_template_no_anchor'];
156
+ }
157
+ }
158
+ }
159
+ //Upgrading to 5.5.0
160
+ if(version_compare($version, '5.5.0', '<'))
161
+ {
162
+ //Translate the old 'page' taxonomy type to BCN_POST_PARENT
163
+ if($defaults['Spost_post_taxonomy_type'] === 'page')
164
+ {
165
+ $opts['Spost_post_taxonomy_type'] = 'BCN_POST_PARENT';
166
+ }
167
+ if(!isset($defaults['Spost_post_taxonomy_referer']))
168
+ {
169
+ $opts['bpost_post_taxonomy_referer'] = false;
170
+ }
171
+ //Loop through all of the post types in the array
172
+ foreach($GLOBALS['wp_post_types'] as $post_type)
173
+ {
174
+ //Check for non-public CPTs
175
+ if(!apply_filters('bcn_show_cpt_private', $post_type->public, $post_type->name))
176
+ {
177
+ continue;
178
+ }
179
+ //We only want custom post types
180
+ if(!$post_type->_builtin)
181
+ {
182
+ //Translate the old 'page' taxonomy type to BCN_POST_PARENT
183
+ if($opts['Spost_' . $post_type->name . '_taxonomy_type'] === 'page')
184
+ {
185
+ $opts['Spost_' . $post_type->name . '_taxonomy_type'] = 'BCN_POST_PARENT';
186
+ }
187
+ //Translate the old 'date' taxonomy type to BCN_DATE
188
+ if($opts['Spost_' . $post_type->name . '_taxonomy_type'] === 'date')
189
+ {
190
+ $opts['Spost_' . $post_type->name . '_taxonomy_type'] = 'BCN_DATE';
191
+ }
192
+ if(!isset($opts['Spost_' . $post_type->name . '_taxonomy_referer']))
193
+ {
194
+ $opts['bpost_' . $post_type->name . '_taxonomy_referer'] = false;
195
+ }
196
+ }
197
+ }
198
+ }
199
+ //Upgrading to 6.0.0
200
+ if(version_compare($version, '6.0.0', '<'))
201
+ {
202
+ //Loop through all of the post types in the array
203
+ foreach($GLOBALS['wp_post_types'] as $post_type)
204
+ {
205
+ if(isset($opts['Spost_' . $post_type->name . '_taxonomy_type']))
206
+ {
207
+ $opts['Spost_' . $post_type->name . '_hierarchy_type'] = $opts['Spost_' . $post_type->name . '_taxonomy_type'];
208
+ unset($opts['Spost_' . $post_type->name . '_taxonomy_type']);
209
+ }
210
+ if(isset($opts['Spost_' . $post_type->name . '_taxonomy_display']))
211
+ {
212
+ $opts['Spost_' . $post_type->name . '_hierarchy_display'] = $opts['Spost_' . $post_type->name . '_taxonomy_display'];
213
+ unset($opts['Spost_' . $post_type->name . '_taxonomy_display']);
214
+ }
215
+ }
216
+ }
217
+ if(version_compare($version, '7.0.0', '<'))
218
+ {
219
+ //Loop through all of the post types in the array
220
+ foreach($GLOBALS['wp_post_types'] as $post_type)
221
+ {
222
+ if(isset($opts['Spost_' . $post_type->name . '_hierarchy_type']))
223
+ {
224
+ $opts['Epost_' . $post_type->name . '_hierarchy_type'] = $opts['Spost_' . $post_type->name . '_hierarchy_type'];
225
+ unset($opts['Spost_' . $post_type->name . '_hierarchy_type']);
226
+ }
227
+ }
228
+ if(isset($opts['Sauthor_name']))
229
+ {
230
+ $opts['Eauthor_name'] = $opts['Sauthor_name'];
231
+ unset($opts['Sauthor_name']);
232
+ }
233
+ }
234
+ }
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: mtekk, hakre
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=FD5XEU783BR8U&lc=US&item_name=Breadcrumb%20NavXT%20Donation&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
4
  Tags: breadcrumb, breadcrumbs, trail, navigation, menu, widget
5
  Requires at least: 4.9
6
- Tested up to: 5.7
7
- Stable tag: 6.6.0
8
- Requires PHP: 5.5
9
  License: GPLv2 or later
10
  Adds breadcrumb navigation showing the visitor's path to their current location.
11
 
@@ -14,6 +14,7 @@ Adds breadcrumb navigation showing the visitor's path to their current location.
14
  Breadcrumb NavXT, the successor to the popular WordPress plugin Breadcrumb Navigation XT, was written from the ground up to be better than its ancestor. This plugin generates locational breadcrumb trails for your WordPress powered blog or website. These breadcrumb trails are highly customizable to suit the needs of just about any website running WordPress. The Administrative interface makes setting options easy, while a direct class access is available for theme developers and more adventurous users.
15
 
16
  = PHP Requirements =
 
17
  Breadcrumb NavXT 5.2 and newer require PHP5.3
18
  Breadcrumb NavXT 5.1.1 and older require PHP5.2
19
 
@@ -49,6 +50,19 @@ Please visit [Breadcrumb NavXT's Documentation](http://mtekk.us/code/breadcrumb-
49
 
50
  == Changelog ==
51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  = 6.6.0 =
53
  Release date: October, 31st 2020
54
 
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=FD5XEU783BR8U&lc=US&item_name=Breadcrumb%20NavXT%20Donation&currency_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted
4
  Tags: breadcrumb, breadcrumbs, trail, navigation, menu, widget
5
  Requires at least: 4.9
6
+ Tested up to: 5.8
7
+ Stable tag: 7.0.0
8
+ Requires PHP: 7.0
9
  License: GPLv2 or later
10
  Adds breadcrumb navigation showing the visitor's path to their current location.
11
 
14
  Breadcrumb NavXT, the successor to the popular WordPress plugin Breadcrumb Navigation XT, was written from the ground up to be better than its ancestor. This plugin generates locational breadcrumb trails for your WordPress powered blog or website. These breadcrumb trails are highly customizable to suit the needs of just about any website running WordPress. The Administrative interface makes setting options easy, while a direct class access is available for theme developers and more adventurous users.
15
 
16
  = PHP Requirements =
17
+ Breadcrumb NavXT 7.0 and newer require PHP7.0
18
  Breadcrumb NavXT 5.2 and newer require PHP5.3
19
  Breadcrumb NavXT 5.1.1 and older require PHP5.2
20
 
50
 
51
  == Changelog ==
52
 
53
+ = 7.0.0 =
54
+ Release date: December, 17th 2021
55
+
56
+ * Behavior change: Within the `bcn_breadcrumb_trail` object instead of passing term id and taxonomy, a WP_Term object is passed instead.
57
+ * Behavior change: Attachments now use parent post type for post type argument.
58
+ * New feature: Moved to adminKit 3.0
59
+ * New feature: Core `bcn_breadcrumb_trail object` now supports multi dimensional trails.
60
+ * New feature: Added `bcn_opts_update_to_save` filter.
61
+ * Bug fix: Fixed parameter order issue in REST controller that resulted in PHP Deprecated message in PHP8.
62
+ * Bug fix: Updated REST controller endpoint registration for better WordPress 5.5+ compatibility.
63
+ * Bug fix: Fixed compatibility issue with Widget settings not saving properly in WordPress 5.8.
64
+ * Bug fix: Fixed issue with the position count parameter within bcn_display when outputting a trail in reverse order.
65
+
66
  = 6.6.0 =
67
  Release date: October, 31st 2020
68
 
uninstall.php CHANGED
@@ -22,7 +22,7 @@
22
  * @author Tom Klingenberg
23
  */
24
  /*
25
- Copyright 2010-2020 John Havlik (email : john.havlik@mtekk.us)
26
 
27
  This program is free software; you can redistribute it and/or modify
28
  it under the terms of the GNU General Public License as published by
@@ -47,7 +47,7 @@ if(!defined('WP_UNINSTALL_PLUGIN'))
47
  header("Status: 404 Not Found");
48
  die();
49
  }
50
- require_once(dirname(__FILE__) . '/includes/class.mtekk_adminkit_uninstaller.php');
51
 
52
  /**
53
  * Breadcrumb NavXT uninstaller class
22
  * @author Tom Klingenberg
23
  */
24
  /*
25
+ Copyright 2010-2021 John Havlik (email : john.havlik@mtekk.us)
26
 
27
  This program is free software; you can redistribute it and/or modify
28
  it under the terms of the GNU General Public License as published by
47
  header("Status: 404 Not Found");
48
  die();
49
  }
50
+ require_once(dirname(__FILE__) . '/includes/adminKit/class-mtekk_adminkit_uninstaller.php');
51
 
52
  /**
53
  * Breadcrumb NavXT uninstaller class