SEO Ultimate - Version 7.6.5.8

Version Description

Download this release

Release Info

Developer SEO Design Solutions
Plugin Icon 128x128 SEO Ultimate
Version 7.6.5.8
Comparing to
See all releases

Code changes from version 7.6.5.7 to 7.6.5.8

modules/class.su-module.php CHANGED
@@ -1,3075 +1,3076 @@
1
- <?php
2
- /**
3
- * The pseudo-abstract class upon which all modules are based.
4
- *
5
- * @abstract
6
- * @since 0.1
7
- */
8
- class SU_Module {
9
-
10
- /********** VARIABLES **********/
11
-
12
- /**
13
- * @since 0.1
14
- * @var string
15
- */
16
- var $module_key;
17
-
18
- /**
19
- * Stores the parent module (an SU_Module object) if this module has a parent.
20
- *
21
- * @since 1.5
22
- * @var SU_Module
23
- */
24
- var $parent_module = null;
25
-
26
- /**
27
- * Stores any child modules as an array of SU_Module objects.
28
- *
29
- * @since 1.5
30
- * @var array
31
- */
32
- var $modules = array();
33
-
34
- /**
35
- * Stores the module file's URL.
36
- *
37
- * @since 0.1
38
- * @var string
39
- */
40
- var $module_url;
41
-
42
- /**
43
- * Stores the URL to the directory containing the module file. Has trailing slash.
44
- *
45
- * @since 1.5
46
- * @var string
47
- */
48
- var $module_dir_url;
49
-
50
- /**
51
- * Stores the module file's URL relative to the plugin directory.
52
- *
53
- * @since 2.1
54
- * @var string
55
- */
56
- var $module_rel_url;
57
-
58
- /**
59
- * Stores the URL to the directory containing the module file, relative to the plugin directory. Has trailing slash.
60
- *
61
- * @since 2.1
62
- * @var string
63
- */
64
- var $module_dir_rel_url;
65
-
66
- /**
67
- * Stores the module's plugin page hook (the full hook with seo_page_ prefix).
68
- * A reconstructed value of the get_plugin_page_hook() function, which is only available after admin init.
69
- *
70
- * @since 0.1
71
- * @var string
72
- */
73
- var $plugin_page_hook;
74
-
75
- /**
76
- * Contains messages that are waiting to be displayed to the user.
77
- *
78
- * @since 0.1
79
- * @var array
80
- */
81
- var $messages = array();
82
-
83
- /**
84
- * Stores the plugin object by reference.
85
- *
86
- * @since 1.5
87
- */
88
- var $plugin = null;
89
-
90
-
91
- /********** CONSTRUCTOR FUNCTION **********/
92
-
93
- /**
94
- * PHP4 constructor that points to the likely-overloaded PHP5 constructor.
95
- *
96
- * @since 0.1
97
- * @uses __construct()
98
- */
99
- /*function SU_Module() {
100
- $this->__construct();
101
- }*/
102
-
103
-
104
- /********** PSEUDO-ABSTRACT FUNCTIONS **********/
105
-
106
- /**
107
- * PHP5 constructor.
108
- *
109
- * @since 0.1
110
- */
111
- function __construct() { }
112
-
113
- /**
114
- * The module's official title.
115
- *
116
- * @since 1.5
117
- *
118
- * @return string
119
- */
120
- static function get_module_title() { return ''; }
121
-
122
- /**
123
- * The title to be used by parent modules.
124
- *
125
- * @since 1.5
126
- *
127
- * @return string
128
- */
129
- function get_module_subtitle() { return isset($this) ? $this->get_module_title() : ''; }
130
-
131
- /**
132
- * The title of the admin page, which is displayed in the <title> and <h2> tags.
133
- * Is the same as the menu title by default.
134
- *
135
- * @since 0.1
136
- *
137
- * @return string The title shown on this module's admin page.
138
- */
139
- function get_page_title() { return isset($this) ? $this->get_module_title() : ''; }
140
-
141
- /**
142
- * The title that appears on the administration navigation menu.
143
- *
144
- * @since 0.1
145
- *
146
- * @return string The title shown on the admin menu.
147
- */
148
-
149
- static function get_menu_title() { return isset($this) ? $this->get_module_title() : ''; }
150
-
151
- /**
152
- * Determines where this module's admin page should appear relative to those of other modules.
153
- * If two modules have the same menu position index, they are sorted alphabetically.
154
- *
155
- * @since 0.1
156
- *
157
- * @return int The menu position index.
158
- */
159
- static function get_menu_pos() { return 10; }
160
-
161
- /**
162
- * Determines where this module's admin contents should appear on the parent page relative to those of other sibling modules.
163
- * If two modules have the same order index, they are sorted alphabetically.
164
- *
165
- * @since 1.5
166
- *
167
- * @return int The child order index.
168
- */
169
- static function get_child_order() { return 999; }
170
-
171
- /**
172
- * The number that should be displayed in a bubble next to the module's menu title.
173
- * A return value of zero means no bubble is shown.
174
- *
175
- * @since 0.1
176
- *
177
- * @return int The number that should be displayed.
178
- */
179
- function get_menu_count() {
180
- $count = 0;
181
- foreach ($this->modules as $key => $module) {
182
- $count += $this->modules[$key]->get_menu_count();
183
- }
184
- return $count;
185
- }
186
-
187
- /**
188
- * Whether or not the module will ever return a non-zero menu count.
189
- *
190
- * @since 1.5
191
- *
192
- * @return boolean
193
- */
194
- static function has_menu_count() { return false; }
195
-
196
- /**
197
- * A descriptive label of the menu count.
198
- *
199
- * @since 0.3
200
- *
201
- * @return string The label.
202
- */
203
- function get_menu_count_label() { return ''; }
204
-
205
- /**
206
- * Indicates under which top-level menu this module's admin page should go.
207
- * Examples: seo (This plugin's SEO menu), options-general.php (The Settings menu)
208
- *
209
- * @since 0.1
210
- *
211
- * @return string The value to pass to WordPress's add_submenu_page() function.
212
- */
213
- function get_menu_parent(){ return 'seo'; }
214
-
215
- /**
216
- * Returns the hook of this module's menu parent.
217
- * Examples: seo (This plugin's SEO menu), settings (The Settings menu), toplevel (The toplevel)
218
- *
219
- * @since 0.1
220
- *
221
- * @return string The hook of the module's menu parent.
222
- */
223
- function get_menu_parent_hook() { return $this->get_menu_parent(); }
224
-
225
- /**
226
- * @since 7.2.5
227
- */
228
- function belongs_in_admin($admin_scope = null) {
229
-
230
- if ($admin_scope === null)
231
- $admin_scope = suwp::get_admin_scope();
232
-
233
- switch ($admin_scope) {
234
- case 'blog':
235
- return true;
236
- break;
237
- case 'network':
238
- case 'user':
239
- default:
240
- return false;
241
- break;
242
- }
243
- }
244
-
245
- /**
246
- * The status (enabled/silenced/hidden) of the module when the module is newly added to the plugin.
247
- *
248
- * @since 1.5
249
- *
250
- * @return int Either SU_MODULE_ENABLED, SU_MODULE_SILENCED, or SU_MODULE_HIDDEN.
251
- */
252
- function get_default_status() { return SU_MODULE_ENABLED; }
253
-
254
- /**
255
- * The module key of this module's parent. Defaults to false (no parent).
256
- *
257
- * @since 0.3
258
- *
259
- * @return string|bool
260
- */
261
- static function get_parent_module() { return false; }
262
-
263
- /**
264
- * Returns an array of admin page tabs; the label is the key and the callback is the value.
265
- *
266
- * @since 1.5
267
- *
268
- * @return array
269
- */
270
- function get_admin_page_tabs() { return array(); }
271
-
272
- /**
273
- * Whether or not the module can "exist on its own."
274
- * Determines whether or not the module appears in the Module Manager.
275
- *
276
- * @since 1.5
277
- *
278
- * @return bool
279
- */
280
- static function is_independent_module() {
281
- return true;
282
- }
283
-
284
- /**
285
- * The array key of the plugin's settings array in which this module's settings are stored.
286
- *
287
- * @since 1.5
288
- *
289
- * @return string
290
- */
291
- function get_settings_key() {
292
- if (isset($this)) {
293
- if (strlen($parent = $this->get_parent_module()) && !$this->is_independent_module())
294
- return $this->plugin->modules[$parent]->get_settings_key();
295
- else
296
- return $this->get_module_key();
297
- } else {
298
- if (strlen($parent = self::get_parent_module()) && !self::is_independent_module()) {
299
- global $seo_ultimate;
300
- return $seo_ultimate->modules[$parent]->get_settings_key();
301
- } else {
302
- if (strlen($parent = self::get_parent_module()) && !self::is_independent_module()) {
303
- global $seo_ultimate;
304
- return $seo_ultimate->get_module_key();
305
- } else {
306
- return false;
307
- }
308
- }
309
- }
310
- }
311
-
312
- /**
313
- * Whether or not this module should be the default screen for the "SEO" menu.
314
- *
315
- * @since 1.5
316
- * @return bool
317
- */
318
- function is_menu_default() { return false; }
319
-
320
- /**
321
- * Called after the module has been constructed and its variables have been filled.
322
- *
323
- * @since 3.9
324
- */
325
- function load() {}
326
-
327
- /**
328
- * Called at WordPress's init hook.
329
- *
330
- * @since 0.1
331
- */
332
- function init() {}
333
-
334
- /**
335
- * Called under 3 circumstances:
336
- * 1. When the SEO Ultimate plugin is activated (not necessarily for the first time)
337
- * 2. When a module is newly registered in the database, which can happen for two reasons:
338
- * a. The plugin is activated *for the first time*
339
- * b. The module has been newly added via a plugin upgrade
340
- * 3. When the module is re-enabled in the Module Manager after being disabled.
341
- *
342
- * Note that this function will be called twice when the plugin is activated for the first time, since this will make #1 and #2 both true.
343
- * If the plugin is deactivated and then reactivated, only #1 will be true.
344
- *
345
- * WARNING: Do not use "$this" in the activate() function. It will not work under condition #3. Check for isset($this) and if false, use self:: instead.
346
- *
347
- * @since 0.1
348
- */
349
- function activate() { }
350
-
351
- /**
352
- * Called under 2 circumstances:
353
- * 1. When the SEO Ultimate plugin is deactivated or uninstalled.
354
- * 2. When the module is disabled in the Module Manager.
355
- *
356
- * @since 7.2.8
357
- */
358
- function deactivate() { }
359
-
360
- /**
361
- * Called when SEO Ultimate has just been upgraded to a new version.
362
- *
363
- * @since 2.1
364
- */
365
- function upgrade() { }
366
-
367
- /**
368
- * Returns an array of default settings. The defaults will be saved in the database if the settings don't exist.
369
- *
370
- * @since 0.1
371
- *
372
- * @return array The default settings. (The setting name is the key, and the default value is the array value.)
373
- */
374
- function get_default_settings() { return array(); }
375
-
376
- /**
377
- * Is called at WordPress' admin_init hook when this module's admin page is showing.
378
- *
379
- * @since 6.0
380
- */
381
- function admin_page_init() { }
382
-
383
- /**
384
- * Is called at WordPress' admin_init hook when the post editor is loaded.
385
- *
386
- * @since 7.3
387
- */
388
- function editor_init() { }
389
-
390
- /**
391
- * The contents of the administration page.
392
- *
393
- * @since 0.1
394
- */
395
- function admin_page_contents() {
396
- $this->children_admin_page_tabs_form();
397
- }
398
-
399
- /**
400
- * Returns a list of possible admin table columns that should be registered in "Screen Options"
401
- *
402
- * @since 2.1
403
- *
404
- * @return array
405
- */
406
- function get_admin_table_columns() {
407
- return array();
408
- }
409
-
410
- /**
411
- * Called at WordPress's load-{page} hook for this module's admin page.
412
- *
413
- * @since 7.0
414
- */
415
- function load_hook() {
416
- $this->add_help_tabs(get_current_screen());
417
- }
418
-
419
- /**
420
- * @since 7.0
421
- */
422
- function add_help_tabs($screen) { }
423
-
424
- /**
425
- * Adds the module's post meta box field HTML to the array.
426
- *
427
- * @since 0.1
428
- *
429
- * @param array $fields The fields array.
430
- * @return array The updated fields array.
431
- */
432
- function postmeta_fields($fields, $screen) { return $fields; }
433
-
434
- /********** INITIALIZATION FUNCTIONALITY **********/
435
-
436
- /**
437
- * If settings are unset, apply the defaults if available.
438
- *
439
- * @since 0.5
440
- * @uses get_default_settings()
441
- * @uses get_setting()
442
- * @uses update_setting()
443
- */
444
- function load_default_settings() {
445
-
446
- $defaults = $this->get_default_settings();
447
- foreach ($defaults as $setting => $default) {
448
- if ($this->get_setting($setting, "{reset}") === "{reset}") {
449
- $this->update_setting($setting, $default, null, null);
450
- }
451
- }
452
- }
453
-
454
-
455
- /********** MODULE FUNCTIONS **********/
456
-
457
- /**
458
- * Returns the array key of the module.
459
- *
460
- * @since 0.1
461
- * @uses $module_key
462
- *
463
- * @return string The module key.
464
- */
465
- function get_module_key() {
466
- if ($this->module_key)
467
- return $this->module_key;
468
- else
469
- //This error will only be triggered if someone has seriously messed with the plugin architecture
470
- die("An SEO Ultimate module did not initialize properly. Perhaps you're trying to load an SEO Ultimate module independent of the plugin?");
471
- }
472
-
473
- /**
474
- * Returns the key of the parent module if there is one; if not, the key of the current module.
475
- *
476
- * @since 2.1
477
- *
478
- * @return string
479
- */
480
- function get_module_or_parent_key() {
481
- return $this->has_enabled_parent() ? $this->get_parent_module() : $this->get_module_key();
482
- }
483
-
484
- /**
485
- * Returns true only if this module has a parent AND that parent is enabled.
486
- *
487
- * @since 7.0
488
- *
489
- * @return bool
490
- */
491
- function has_enabled_parent() {
492
- return (strlen($p = $this->get_parent_module()) && $this->plugin->module_exists($p));
493
- }
494
-
495
- /**
496
- * Returns the absolute URL of the module's admin page.
497
- *
498
- * @since 0.7
499
- *
500
- * @param string|false $key The key of the module for which to generate the admin URL. Optional.
501
- * @return string The absolute URL to the admin page.
502
- */
503
- function get_admin_url($key = false) {
504
-
505
- $anchor = '';
506
- if ($key === false) {
507
- if (($key = $this->get_parent_module()) && $this->plugin->module_exists($key)) {
508
-
509
- $tabs = $this->get_admin_page_tabs();
510
- if (!is_array($tabs))
511
- return false;
512
-
513
- if (count($tabs)) {
514
- $first_tab = reset($tabs);
515
- $anchor = '#' . $first_tab['id'];
516
- } else {
517
- $anchor = '#' . $this->plugin->key_to_hook($this->get_module_key());
518
- }
519
- } else
520
- $key = $this->get_module_key();
521
- }
522
-
523
- if (!$this->plugin->call_module_func($key, 'belongs_in_admin', $belongs_in_admin) || !$belongs_in_admin)
524
- return false;
525
-
526
- if (!$this->plugin->call_module_func($key, 'get_menu_title', $menu_title) || !$menu_title)
527
- return false;
528
-
529
- $basepage = 'admin.php';
530
- if ($this->plugin->call_module_func($key, 'get_menu_parent', $custom_basepage) && sustr::endswith($custom_basepage, '.php'))
531
- $basepage = $custom_basepage;
532
-
533
- if (is_network_admin() && $this->belongs_in_admin('network'))
534
- $admin_url = 'network_admin_url';
535
- else
536
- $admin_url = 'admin_url';
537
-
538
- return $admin_url($basepage.'?page='.$this->plugin->key_to_hook($key).$anchor);
539
- }
540
-
541
- /**
542
- * Returns an <a> link to the module's admin page, if the module is enabled.
543
- *
544
- * @since 1.0
545
- * @uses get_admin_url()
546
- *
547
- * @param string|false $key The key of the module for which to generate the admin URL.
548
- * @param string $label The text to go inside the <a> element.
549
- * @return string The <a> element, if the module exists; otherwise, the label by itself.
550
- */
551
- function get_admin_link($key, $label) {
552
-
553
- if ($key == false || $this->plugin->module_exists($key))
554
- return sprintf('<a href="%s">%s</a>', $this->get_admin_url($key), $label);
555
- else
556
- return $label;
557
- }
558
-
559
- /**
560
- * Returns a boolean indicating whether the user is currently viewing this module's admin page.
561
- *
562
- * @since 1.1.1
563
- *
564
- * @return bool Whether the user is currently viewing this module's admin page.
565
- */
566
- function is_module_admin_page() {
567
- if (is_admin()) {
568
- global $plugin_page;
569
- if (strcmp($plugin_page, $this->plugin->key_to_hook($this->get_module_or_parent_key())) == 0) return true;
570
- }
571
-
572
- return false;
573
- }
574
-
575
- /**
576
- * Returns the filename of the module's icon URL.
577
- *
578
- * @since 1.5
579
- *
580
- * @return string
581
- */
582
- function get_menu_icon_filename() {
583
- $filenames = array(
584
- $this->get_settings_key()
585
- , $this->get_module_key()
586
- , $this->get_parent_module()
587
- );
588
-
589
- foreach ($filenames as $filename) {
590
- $image = $this->module_dir_url.$filename.'.png';
591
- if (is_readable($image)) return $image;
592
- }
593
-
594
- return '';
595
- }
596
-
597
-
598
- /********** CHILD MODULE FUNCTIONS **********/
599
-
600
- /**
601
- * Finds child modules of this module and fills $this->modules accordingly.
602
- *
603
- * @since 1.5
604
- */
605
- function load_child_modules() {
606
- foreach ($this->plugin->modules as $key => $x_module) {
607
- if ($key != $this->get_module_key()) {
608
- $module =& $this->plugin->modules[$key];
609
- if ($module->get_parent_module() == $this->get_module_key()) {
610
- $module->parent_module =& $this;
611
- $this->modules[$key] =& $module;
612
- }
613
- }
614
- }
615
-
616
- if (count($this->modules) > 0)
617
- @uasort($this->modules, array(&$this, 'module_sort_callback'));
618
- }
619
-
620
- /**
621
- * Returns an array of this module's admin tabs plus those of its children.
622
- *
623
- * @since 1.5
624
- * @return array
625
- */
626
- function get_children_admin_page_tabs() {
627
- $tabs = $this->get_admin_page_tabs();
628
- if (!is_array($tabs)) $tabs = array();
629
-
630
- foreach ($this->modules as $key => $x_module) {
631
- $module =& $this->modules[$key];
632
-
633
- if ($module->belongs_in_admin()) {
634
- $child_tabs = $module->get_admin_page_tabs();
635
-
636
- if (is_array($child_tabs)) {
637
-
638
- if (empty($child_tabs))
639
- $child_tabs[] = array(
640
- 'title' => $module->get_module_subtitle()
641
- , 'id' => $this->plugin->key_to_hook($key)
642
- , 'callback' => array(&$module, 'admin_page_contents')
643
- );
644
-
645
- foreach ($child_tabs as $child_tab) {
646
- if (is_array($child_tab) && !is_array($child_tab['callback']))
647
- $child_tab['callback'] = array(&$module, $child_tab['callback']);
648
-
649
- $tabs[] = $child_tab;
650
- }
651
- }
652
- }
653
- }
654
-
655
- return $tabs;
656
- }
657
-
658
- /**
659
- * Outputs this module's admin tabs plus those of its children.
660
- *
661
- * @since 1.5
662
- */
663
- function children_admin_page_tabs() {
664
- if (count($tabs = $this->get_children_admin_page_tabs()))
665
- $this->admin_page_tabs($tabs);
666
- }
667
-
668
- /**
669
- * Outputs a form containing this module's admin tabs plus those of its children.
670
- *
671
- * @since 1.5
672
- */
673
- function children_admin_page_tabs_form() {
674
- if (count($tabs = $this->get_children_admin_page_tabs())) {
675
- echo "\n\n<div class='row'>\n";
676
- echo "\n\n<div class='col-sm-8 col-md-9'>\n";
677
-
678
- $this->admin_form_start(false, false);
679
- $this->admin_page_tabs($tabs);
680
- $this->admin_form_end(null, false);
681
-
682
- echo "\n\n</div>\n";
683
- echo "\n\n<div class='col-sm-4 col-md-3'>\n";
684
- $this->promo_sdf_banners();
685
- echo "\n\n</div>\n";
686
- echo "\n\n</div>\n";
687
- }
688
- }
689
-
690
- /**
691
- * Outputs the admin pages of this module's children, one after the other.
692
- *
693
- * @since 1.5
694
- */
695
- function children_admin_pages() {
696
- foreach ($this->modules as $key => $x_module) {
697
- echo "<div id='" . $this->plugin->key_to_hook($key) . "'>\n";
698
- $this->modules[$key]->admin_subheader($this->modules[$key]->get_module_subtitle());
699
- $this->modules[$key]->admin_page_contents();
700
- echo "</div>\n";
701
- }
702
- }
703
-
704
- /**
705
- * Outputs a form containing the admin pages of this module's children, outputted one after the other.
706
- *
707
- * @since 1.5
708
- */
709
- function children_admin_pages_form() {
710
- if (count($this->modules)) {
711
- $this->admin_form_start(false, false);
712
- $this->children_admin_pages();
713
- $this->admin_form_end(null, false);
714
- } else
715
- $this->print_message('warning', sprintf(__('All the modules on this page have been disabled. You can re-enable them using the <a href="%s">Module Manager</a>.', 'seo-ultimate'), $this->get_admin_url('modules')));
716
- }
717
-
718
- /**
719
- * Compares two modules to determine which of the two should be displayed first on the parent page.
720
- * Sorts by child order first, and title second.
721
- * Works as a uasort() callback.
722
- *
723
- * @since 1.5
724
- * @uses SU_Module::get_child_order()
725
- * @uses SU_Module::get_module_subtitle()
726
- *
727
- * @param SU_Module $a The first module to compare.
728
- * @param SU_Module $b The second module to compare.
729
- * @return int This will be -1 if $a comes first, or 1 if $b comes first.
730
- */
731
- function module_sort_callback($a, $b) {
732
-
733
- if ($a->get_child_order() == $b->get_child_order()) {
734
- return strcmp($a->get_module_subtitle(), $b->get_module_subtitle());
735
- }
736
-
737
- return ($a->get_child_order() < $b->get_child_order()) ? -1 : 1;
738
- }
739
-
740
- /********** SETTINGS FUNCTIONS **********/
741
-
742
- /**
743
- * Retrieves the given setting from a module's settings array.
744
- *
745
- * @since 0.1
746
- * @uses get_settings_key()
747
- *
748
- * @param string $key The name of the setting to retrieve.
749
- * @param mixed $default What should be returned if the setting does not exist. Optional.
750
- * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
751
- * @return mixed The value of the setting, or the $default variable.
752
- */
753
- function get_setting($key, $default=null, $module=null, $sneakpeak=false) {
754
- if (!$module) $module = $this->get_settings_key();
755
-
756
- $msdata = (array)get_option("seo_ultimate_module_$module", array());
757
-
758
- if ($sneakpeak && $this->is_action('update'))
759
- $setting = stripslashes(isset($_POST[$key]) ? $_POST[$key] : null);
760
- elseif (isset($msdata[$key]))
761
- $setting = $msdata[$key];
762
- else
763
- $setting = $default;
764
-
765
- $setting = apply_filters("su_get_setting-$module", $setting, $key);
766
- $setting = apply_filters("su_get_setting-$module-$key", $setting, $key);
767
-
768
- return $setting;
769
- }
770
-
771
- /**
772
- * Sets a value in the module's settings array.
773
- *
774
- * @since 0.1
775
- * @uses get_settings_key()
776
- *
777
- * @param string $key The key of the setting to be changed.
778
- * @param string $value The new value to assign to the setting.
779
- * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
780
- */
781
- function update_setting($key, $value, $module=null, $array_key=null) {
782
- if (!$module) $module = $this->get_settings_key();
783
-
784
- $msdata = (array)get_option("seo_ultimate_module_$module", array());
785
-
786
- $use_custom = apply_filters("su_custom_update_setting-$module-$key", false, $value, $key) ||
787
- apply_filters("su_custom_update_setting-$module", false, $value, $key);
788
-
789
- if (!$use_custom) {
790
- if ($array_key)
791
- $msdata[$key][$array_key] = $value;
792
- else
793
- $msdata[$key] = $value;
794
- }
795
-
796
- update_option("seo_ultimate_module_$module", $msdata);
797
- }
798
-
799
- /**
800
- * Gets a setting's value, deletes the setting, and returns the value.
801
- *
802
- * @since 2.1
803
- * @uses get_settings_key()
804
- *
805
- * @param string $key The name of the setting to retrieve/delete.
806
- * @param mixed $default What should be returned if the setting does not exist. Optional.
807
- * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
808
- * @return mixed The value of the setting, or the $default variable.
809
- */
810
- function flush_setting($key, $default=null, $module=null) {
811
- $setting = $this->get_setting($key, $default, $module); //We need to retrieve the setting before deleting it
812
- $this->delete_setting($key, $module);
813
- return $setting;
814
- }
815
-
816
- /**
817
- * Deletes a module setting.
818
- *
819
- * @since 2.1
820
- * @uses get_settings_key()
821
- *
822
- * @param string $key The name of the setting to delete.
823
- * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
824
- */
825
- function delete_setting($key, $module=null, $array_key = null) {
826
- if (!$module) $module = $this->get_settings_key();
827
-
828
- $msdata = (array)get_option("seo_ultimate_module_$module", array());
829
-
830
- if (isset($msdata[$key])) {
831
- if ($array_key) {
832
- if (isset($msdata[$key][$array_key]))
833
- unset($msdata[$key][$array_key]);
834
- } else {
835
- unset($msdata[$key]);
836
- }
837
- }
838
- }
839
-
840
- /**
841
- * Returns a default setting. Only use this function if a default is indeed provided!
842
- *
843
- * @since 1.3
844
- * @uses get_default_settings()
845
- *
846
- * @param string $key The name of the setting whose default to retrieve.
847
- * @return mixed The default value for the setting.
848
- */
849
- function get_default_setting($key) {
850
- $defaults = $this->get_default_settings();
851
- return $defaults[$key];
852
- }
853
-
854
-
855
- /********** ADMIN PAGE FUNCTIONS **********/
856
-
857
- /**
858
- * Displays the beginning, contents, and end of the module's administration page.
859
- *
860
- * @since 0.1
861
- * @uses admin_page_start()
862
- * @uses admin_page_contents()
863
- * @uses admin_page_end()
864
- */
865
- function admin_page() {
866
- if (!apply_filters('su_custom_admin_page-'.$this->get_module_key(), false)) {
867
- $this->admin_page_start();
868
- $this->admin_page_contents();
869
- $this->admin_page_end();
870
- }
871
- }
872
-
873
- /**
874
- * Outputs the starting code for an administration page:
875
- * wrapper, ID'd <div>, icon, and title
876
- *
877
- * @since 0.1
878
- * @uses admin_footer() Hooked into WordPress's in_admin_footer action.
879
- * @uses get_module_key()
880
- * @uses get_page_title()
881
- *
882
- * @param string $icon The ID that should be applied to the icon element. The icon is loaded via CSS based on the ID. Optional.
883
- */
884
- function admin_page_start($icon = 'options-general') {
885
-
886
- //Add our custom footer attribution
887
- add_action('in_admin_footer', array(&$this, 'admin_footer'));
888
-
889
- //Output the beginning of the admin screen
890
- echo "<div class=\"wrap\">\n";
891
-
892
- if (strcmp($pclass = strtolower(get_parent_class($this)), 'su_module') != 0)
893
- $class = ' '.str_replace('_', '-', $pclass);
894
- else
895
- $class = '';
896
-
897
- echo "<div id=\"su-".su_esc_attr($this->get_module_key())."\" class=\"sdf-admin$class\">\n";
898
- screen_icon($icon);
899
- echo "\n<h2>".$this->get_page_title()."</h2>\n";
900
- }
901
-
902
- /**
903
- * Outputs an administration page subheader (an <h4> tag).
904
- *
905
- * @since 0.1
906
- *
907
- * @param string $title The text to output.
908
- */
909
- function admin_subheader($title, $id=false) {
910
- if ($id) $id = ' id="' . su_esc_attr($id) . '"';
911
- echo "<h4 class='su-subheader'$id>$title</h4>\n";
912
- }
913
-
914
- /**
915
- * Outputs an administration form table subheader.
916
- *
917
- * @since 0.1
918
- *
919
- * @param string $title The text to output.
920
- */
921
- function admin_form_subheader($title) {
922
- echo "<tr><th colspan='2'><strong>$title</strong></th></tr>\n";
923
- }
924
-
925
- /**
926
- * Outputs the ending code for an administration page.
927
- *
928
- * @since 0.1
929
- */
930
- function admin_page_end() {
931
- echo "\n</div>\n</div>\n";
932
- }
933
-
934
- /**
935
- * Outputs a tab control and loads the current tab.
936
- *
937
- * @since 0.7
938
- *
939
- * @param array $tabs Array (id => __, title => __, callback => __)
940
- * @param bool $table Whether or not the tab contents should be wrapped in a form table.
941
- */
942
- function admin_page_tabs($tabs=array(), $table=false) {
943
- $this->plugin->tabs($tabs, $table, $this);
944
- }
945
-
946
- /**
947
- * Adds the hook necessary to initialize the admin page tabs.
948
- *
949
- * @since 0.8
950
- */
951
- function admin_page_tabs_init() {
952
- add_action('admin_enqueue_scripts', array(&$this, 'admin_page_tabs_js'));
953
- }
954
-
955
- /**
956
- * Enqueues the JavaScript needed for the admin page tabs.
957
- *
958
- * @since 0.8
959
- * @uses is_module_admin_page()
960
- */
961
- function admin_page_tabs_js() {
962
- if ($this->is_module_admin_page())
963
- wp_enqueue_script('jquery-ui-tabs');
964
- }
965
-
966
- /**
967
- * Adds plugin/module information to the admin footer.
968
- *
969
- * @since 0.1
970
- * @uses SU_PLUGIN_URI
971
- * @uses SU_PLUGIN_NAME
972
- * @uses SU_AUTHOR_URI
973
- * @uses SU_AUTHOR
974
- */
975
- function admin_footer() {
976
- printf(__('%1$s | %2$s %3$s by %4$s', 'seo-ultimate'),
977
- $this->get_module_title(),
978
- '<a href="'.SU_PLUGIN_URI.'" target="_blank" rel="nofollow">'.__(SU_PLUGIN_NAME, 'seo-ultimate').'</a>',
979
- SU_VERSION,
980
- '<a href="'.SU_AUTHOR_URI.'" target="_blank" rel="nofollow">'.__(SU_AUTHOR, 'seo-ultimate').'</a>'
981
- );
982
-
983
- echo "<br />";
984
- }
985
-
986
- /**
987
- * Returns tabs for post/taxonomy meta editing tables.
988
- *
989
- * @since 2.9
990
- * @uses get_postmeta_edit_tabs()
991
- * @uses get_taxmeta_edit_tabs()
992
- *
993
- * @param array $fields The array of meta fields that the user can edit with the tables.
994
- */
995
- function get_meta_edit_tabs($fields) {
996
- return array_merge(
997
- $this->get_postmeta_edit_tabs($fields)
998
- ,$this->get_taxmeta_edit_tabs($fields)
999
- );
1000
- }
1001
-
1002
- /**
1003
- * Returns tabs for post meta editing tables.
1004
- *
1005
- * @since 2.9
1006
- *
1007
- * @param array $fields The array of meta fields that the user can edit with the tables.
1008
- */
1009
- function get_postmeta_edit_tabs($fields) {
1010
-
1011
- $types = get_post_types(array('public' => true), 'objects');
1012
-
1013
- //Turn the types array into a tabs array
1014
- $tabs = array();
1015
- foreach ($types as $type)
1016
- $tabs[$type->name] = array(
1017
- 'title' => $type->labels->name
1018
- , 'id' => 'su-' . $type->name
1019
- , 'callback' => array('meta_edit_tab', 'post', 'su-' . $type->name, $type->name, $type->labels->singular_name, $fields)
1020
- );
1021
- return $tabs;
1022
- }
1023
-
1024
- /**
1025
- * Returns tabs for taxonomy meta editing tables.
1026
- *
1027
- * @since 2.9
1028
- *
1029
- * @param array $fields The array of meta fields that the user can edit with the tables.
1030
- */
1031
- function get_taxmeta_edit_tabs($fields) {
1032
- $types = suwp::get_taxonomies();
1033
-
1034
- //Turn the types array into a tabs array
1035
- $tabs = array();
1036
- foreach ($types as $name => $type) {
1037
- if ($type->labels->name) {
1038
- $tabs[] = array(
1039
- 'title' => $type->labels->name
1040
- , 'id' => 'su-' . $name
1041
- , 'callback' => array('meta_edit_tab', 'term', 'su-' . $name, $name, $type->labels->singular_name, $fields)
1042
- );
1043
- }
1044
- }
1045
- return $tabs;
1046
- }
1047
-
1048
- /**
1049
- * Outputs the contents of a meta editing tab.
1050
- *
1051
- * @since 2.9
1052
- */
1053
- function meta_edit_tab($genus, $tab, $type, $type_label, $fields) {
1054
- if (!$this->meta_edit_table($genus, $tab, $type, $type_label, $fields))
1055
- $this->print_message('info', __('Your site currently doesn&#8217;t have any public items of this type.', 'seo-ultimate'));
1056
- }
1057
-
1058
- /**
1059
- * Outputs the contents of a meta editing table.
1060
- *
1061
- * @since 2.9
1062
- *
1063
- * @param string $genus The type of object being handled (either 'post' or 'term')
1064
- * @param string $tab The ID of the current tab; used to generate a URL hash (e.g. #$tab)
1065
- * @param string $type The type of post/taxonomy type being edited (examples: post, page, attachment, category, post_tag)
1066
- * @param string $type_label The singular label for the post/taxonomy type (examples: Post, Page, Attachment, Category, Post Tag)
1067
- * @param array $fields The array of meta fields that the user can edit with the tables. The data for each meta field are stored in an array with these elements: "type" (can be textbox, textarea, or checkbox), "name" (the meta field, e.g. title or description), "term_settings_key" (the key of the setting for cases when term meta data are stored in the settings array), and "label" (the internationalized label of the field, e.g. "Meta Description" or "Title Tag")
1068
- */
1069
- function meta_edit_table($genus, $tab, $type, $type_label, $fields) {
1070
-
1071
- //Pseudo-constant
1072
- $per_page = 100;
1073
-
1074
- //Sanitize parameters
1075
- if (!is_array($fields) || !count($fields)) return false;
1076
- if (!isset($fields[0]) || !is_array($fields[0])) $fields = array($fields);
1077
-
1078
- //Get search query
1079
- $type_s = $type . '_s';
1080
- $search = isset($_REQUEST[$type_s]) ? $_REQUEST[$type_s] : '';
1081
-
1082
- //Save meta if applicable
1083
- if ($is_update = ($this->is_action('update') && !strlen(trim($search)))) {
1084
- foreach ($_POST as $key => $value) {
1085
- $value = stripslashes($value);
1086
- if (sustr::startswith($key, $genus.'_'))
1087
- foreach ($fields as $field)
1088
- if (preg_match("/{$genus}_([0-9]+)_{$field['name']}/", $key, $matches)) {
1089
- $id = (int)$matches[1];
1090
- switch ($genus) {
1091
- case 'post': update_post_meta($id, "_su_{$field['name']}", $value); break;
1092
- case 'term': $this->update_setting($field['term_settings_key'], $value, null, $id); break;
1093
- }
1094
- continue 2; //Go to next $_POST item
1095
- }
1096
- }
1097
- }
1098
-
1099
- $pagenum = isset( $_GET[$type . '_paged'] ) ? absint( $_GET[$type . '_paged'] ) : 0;
1100
- if ( empty($pagenum) ) $pagenum = 1;
1101
-
1102
- //Load up the objects based on the genus
1103
- switch ($genus) {
1104
- case 'post':
1105
-
1106
- //Get the posts
1107
- wp(array(
1108
- 'post_type' => $type
1109
- , 'posts_per_page' => $per_page
1110
- , 'post_status' => 'any'
1111
- , 'paged' => $pagenum
1112
- , 'order' => 'ASC'
1113
- , 'orderby' => 'title'
1114
- , 's' => $search
1115
- ));
1116
- global $wp_query;
1117
- $objects = &$wp_query->posts;
1118
-
1119
- $num_pages = $wp_query->max_num_pages;
1120
- $total_objects = $wp_query->found_posts;
1121
-
1122
- break;
1123
-
1124
- case 'term':
1125
- $objects = get_terms($type, array('search' => $search));
1126
- $total_objects = count($objects);
1127
- $num_pages = ceil($total_objects / $per_page);
1128
- $objects = array_slice($objects, $per_page * ($pagenum-1), $per_page);
1129
- break;
1130
- default:
1131
- return false;
1132
- break;
1133
- }
1134
-
1135
- if ($total_objects < 1) return false;
1136
-
1137
- echo "\n<div class='su-meta-edit-table'>\n";
1138
-
1139
- $page_links = paginate_links( array(
1140
- 'base' => esc_url( add_query_arg( $type . '_paged', '%#%' ) ) . '#' . $tab
1141
- , 'format' => ''
1142
- , 'prev_text' => __('&laquo;')
1143
- , 'next_text' => __('&raquo;')
1144
- , 'total' => $num_pages
1145
- , 'current' => $pagenum
1146
- ));
1147
-
1148
- if ( $page_links ) {
1149
- $page_links_text = '<div class="tablenav"><div class="tablenav-pages">';
1150
- $page_links_text .= sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s' ) . '</span>%s',
1151
- number_format_i18n( ( $pagenum - 1 ) * $per_page + 1 ),
1152
- number_format_i18n( min( $pagenum * $per_page, $total_objects ) ),
1153
- number_format_i18n( $total_objects ),
1154
- $page_links
1155
- );
1156
- $page_links_text .= "</div></div>\n";
1157
-
1158
- echo $page_links_text;
1159
- } else $page_links_text = '';
1160
-
1161
- //Get object identification headers
1162
- $headers = array(
1163
- 'actions' => __('Actions', 'seo-ultimate')
1164
- , 'id' => __('ID', 'seo-ultimate')
1165
- , 'name' => $type_label
1166
- );
1167
-
1168
- //Get meta field headers
1169
- foreach ($fields as $field) {
1170
- $headers[$field['name']] = $field['label'];
1171
- }
1172
-
1173
- //Output all headers
1174
- $this->admin_wftable_start($headers);
1175
-
1176
- //Output rows
1177
- foreach ($objects as $object) {
1178
-
1179
- switch ($genus) {
1180
- case 'post':
1181
- $id = intval($object->ID);
1182
- $name = $object->post_title;
1183
- $view_url = get_permalink($id);
1184
- $edit_url = get_edit_post_link($id);
1185
-
1186
- $status_obj = get_post_status_object($object->post_status);
1187
- switch ($object->post_status) {
1188
- case 'publish': $status = ''; break;
1189
- case 'inherit': $status = ''; break;
1190
- case 'auto-draft': continue; break;
1191
- default: $status = $status_obj->label; break;
1192
- }
1193
-
1194
- if ($status)
1195
- $name .= "<span class='su-meta-table-post-status'> &mdash; $status</span>";
1196
-
1197
- break;
1198
- case 'term':
1199
- if (!isset($object->term_taxonomy_id)) {
1200
- $id = intval($object->term_id);
1201
- $view_url = get_term_link($id, $type);
1202
- }
1203
- else{
1204
- $id = intval($object->term_taxonomy_id);
1205
- $view_url = get_term_link(intval($object->term_id), $type);
1206
- }
1207
- $name = $object->name;
1208
-
1209
- $edit_url = suwp::get_edit_term_link($id, $type);
1210
- break;
1211
- default: return false; break;
1212
- }
1213
-
1214
- $view_url = su_esc_attr($view_url);
1215
- $edit_url = su_esc_attr($edit_url);
1216
-
1217
- $actions = array(sprintf('<a href="%s">%s</a>', $view_url, __('View', 'seo-ultimate')));
1218
- if ($edit_url)
1219
- $actions[] = sprintf('<a href="%s">%s</a>', $edit_url, __('Edit', 'seo-ultimate'));
1220
- $actions = implode(' | ', $actions);
1221
-
1222
- $cells = compact('actions', 'id', 'name');
1223
-
1224
- //Get meta field cells
1225
- foreach ($fields as $field) {
1226
- $inputid = "{$genus}_{$id}_{$field['name']}";
1227
-
1228
- switch ($genus) {
1229
- case 'post':
1230
- $value = $this->get_postmeta($field['name'], $id);
1231
- break;
1232
- case 'term':
1233
- $value = $this->get_setting($field['term_settings_key'], array());
1234
- $value = isset($value[$id]) ? $value[$id] : null;
1235
- break;
1236
- }
1237
-
1238
- if ($is_update && $field['type'] == 'checkbox' && $value == '1' && !isset($_POST[$inputid]))
1239
- switch ($genus) {
1240
- case 'post': delete_post_meta($id, "_su_{$field['name']}"); $value = 0; break;
1241
- case 'term': $this->update_setting($field['term_settings_key'], false, null, $id); break;
1242
- }
1243
-
1244
- $cells[$field['name']] = $this->get_input_element(
1245
- $field['type'] //Type
1246
- , $inputid
1247
- , $value
1248
- , isset($field['options']) ? $field['options'] : false
1249
- );
1250
- }
1251
-
1252
- //Output all cells
1253
- $this->table_row($cells, $id, $type);
1254
- }
1255
-
1256
- //End table
1257
- $this->admin_wftable_end();
1258
-
1259
- echo $page_links_text;
1260
-
1261
- echo "</div>\n";
1262
-
1263
- return true;
1264
- }
1265
-
1266
- /**
1267
- * Returns the HTML for a given type of input element, without any surrounding <td> elements etc.
1268
- *
1269
- * @since 2.9
1270
- *
1271
- * @param string $type The type of input element (can be textbox, textarea, or checkbox)
1272
- * @param string $inputid The name/ID of the input element
1273
- * @param string $value The current value of the field
1274
- * @return string
1275
- */
1276
- function get_input_element($type, $name, $value=null, $extra=false, $inputid=true) {
1277
- if ($value === null) $value = $this->get_setting($name);
1278
-
1279
- if ($inputid === true) $inputid = $name;
1280
- if (strlen($inputid)) $inputid = " id='".su_esc_attr($inputid)."'";
1281
-
1282
- //Get HTML element
1283
- switch ($type) {
1284
- case 'textbox':
1285
- $value = su_esc_editable_html($value);
1286
- $placeholder = $extra ? " placeholder='" . su_esc_attr($extra) . "'" : '';
1287
- return "<input name='$name'$inputid value='$value'$placeholder type='text' class='form-control input-sm textbox regular-text' />";
1288
- break;
1289
- case 'textarea':
1290
- $value = su_esc_editable_html($value);
1291
- return "<textarea name='$name'$inputid type='text' rows='3' cols='50' class='textarea form-control regular-text'>$value</textarea>";
1292
- break;
1293
- case 'checkbox':
1294
- $checked = $value ? " checked='checked'" : '';
1295
- $html = "<input name='$name'$inputid value='1' type='checkbox' class='checkbox'$checked />";
1296
- if (is_string($extra)) {
1297
- $extra = su_esc_html($extra);
1298
- $html = "<label>$html&nbsp;$extra</label>";
1299
- }
1300
- return $html;
1301
- break;
1302
- case 'dropdown':
1303
- $html = "<select name='$name'$inputid onchange='javascript:su_toggle_select_children(this)' class='dropdown'>";
1304
- if (is_array($extra)) $html .= suhtml::option_tags($extra, $value); else $html .= $extra;
1305
- $html .= "</select>";
1306
- return $html;
1307
- break;
1308
- case 'hidden':
1309
- return "<input name='$name'$inputid value='$value' type='hidden' />";
1310
- break;
1311
- case 'jlsuggest':
1312
- $params = isset($extra['params']) ? $extra['params'] : '';
1313
- $placeholder = isset($extra['placeholder']) ? $extra['placeholder'] : '';
1314
-
1315
- return $this->get_jlsuggest_box($name, $value, $params, $placeholder);
1316
- break;
1317
- }
1318
-
1319
- return '';
1320
- }
1321
-
1322
- /**
1323
- * Creates an admin form subsection.
1324
- *
1325
- * @since 3.8
1326
- * @uses get_setting()
1327
- * @see get_input_element()
1328
- *
1329
- * @param string $field
1330
- * @param string|null $current_value
1331
- * @param string $trigger_value
1332
- * @param string $html
1333
- * @return string
1334
- */
1335
- function get_admin_form_subsection($field, $current_value, $trigger_value, $html) {
1336
- if ($current_value === null) $current_value = $this->get_setting($field);
1337
- $hidden = ($current_value == $trigger_value) ? '' : ' hidden';
1338
-
1339
- $field = su_esc_attr($field);
1340
- $trigger_value = su_esc_attr($trigger_value);
1341
- $html = "<div class='su_{$field}_{$trigger_value}_subsection$hidden'>$html</div>";
1342
- return $html;
1343
- }
1344
-
1345
- /**
1346
- * Creates multiple admin form subsections.
1347
- *
1348
- * @since 3.8
1349
- * @uses get_admin_form_subsection()
1350
- * @see get_input_element()
1351
- *
1352
- * @param string $field
1353
- * @param array $subsections Array of ($field => $trigger_value)
1354
- * @return string
1355
- */
1356
- function get_admin_form_subsections($field, $current_value, $subsections) {
1357
- $allhtml = '';
1358
- if (!in_array($current_value, $subsection_keys = array_keys($subsections))) $current_value = $subsection_keys[0];
1359
- foreach ($subsections as $trigger_value => $html)
1360
- $allhtml .= $this->get_admin_form_subsection($field, $current_value, $trigger_value, $html);
1361
- return $allhtml;
1362
- }
1363
-
1364
-
1365
- /********** ADMIN FORM FUNCTIONS **********/
1366
-
1367
- /**
1368
- * Begins an administration form.
1369
- * Outputs a subheader if provided, queues a success message upon settings update, outputs queued messages,
1370
- * opens a form tag, outputs a nonce field and other WordPress fields, and begins a form table.
1371
- *
1372
- * @since 0.1
1373
- * @uses SEO_Ultimate::key_to_hook()
1374
- * @uses get_module_key()
1375
- * @uses admin_subheader()
1376
- * @uses is_action()
1377
- * @uses print_message()
1378
- * @uses get_parent_module()
1379
- *
1380
- * @param mixed $header The text of the subheader that should go right before the form. Optional.
1381
- * @param boolean $table Whether or not to start a form table.
1382
- */
1383
- function admin_form_start($header = false, $table = true, $form = true) {
1384
-
1385
- if ($header) $this->admin_subheader($header);
1386
-
1387
- if ($form) {
1388
- $hook = $this->plugin->key_to_hook($this->get_module_or_parent_key());
1389
- if ($this->is_action('update')) $this->print_message('success', __('Settings updated.', 'seo-ultimate'));
1390
- echo "<form id='su-admin-form' class='form-horizontal' method='post' action='?page=$hook'>\n";
1391
- settings_fields($hook);
1392
- }
1393
-
1394
- echo "\n";
1395
- //if ($table) echo "<table class='form-table'>\n";
1396
- }
1397
-
1398
- /**
1399
- * Ends an administration form.
1400
- * Closes the table tag, outputs a "Save Changes" button, and closes the form tag.
1401
- *
1402
- * @since 0.1
1403
- * @uses get_parent_module()
1404
- *
1405
- * @param string|false $button The label of the submit button.
1406
- * @param boolean $table Whether or not a form table should be ended.
1407
- */
1408
- function admin_form_end($button = null, $table = true) {
1409
-
1410
- if ($button === null) $button = __('Save Changes'); //This string is used in normal WP, so we don't need a textdomain
1411
- //if ($table) echo "</table>\n";
1412
-
1413
- if ($button !== false) {
1414
- ?>
1415
- <p class="submit">
1416
- <input type="submit" class="button-primary" value="<?php echo $button ?>" />
1417
- </p>
1418
- </form>
1419
- <?php
1420
- }
1421
- }
1422
-
1423
- /**
1424
- * Begins an admin form table.
1425
- *
1426
- * @since 1.5
1427
- */
1428
- function admin_form_table_start() {
1429
- //echo "<table class='form-table'>\n";
1430
- }
1431
-
1432
- /**
1433
- * Ends an admin form table
1434
- *
1435
- * @since 1.5
1436
- */
1437
- function admin_form_table_end() {
1438
- //echo "</table>\n";
1439
- }
1440
-
1441
- /**
1442
- * @since 5.8
1443
- */
1444
- function child_admin_form_start($table=true) {
1445
- if ($this->get_parent_module() && $this->plugin->module_exists($this->get_parent_module())) {
1446
- if ($table) $this->admin_form_table_start();
1447
- } else {
1448
- $this->admin_form_start(false, $table);
1449
- }
1450
- }
1451
-
1452
- /**
1453
- * @since 5.8
1454
- */
1455
- function child_admin_form_end($table=true) {
1456
- if ($this->get_parent_module() && $this->plugin->module_exists($this->get_parent_module())) {
1457
- if ($table) $this->admin_form_table_end();
1458
- } else {
1459
- $this->admin_form_end(null, $table);
1460
- }
1461
- }
1462
-
1463
- /**
1464
- * Begins a "widefat" WordPress table.
1465
- *
1466
- * @since 1.8
1467
- *
1468
- * @param $headers Array of (CSS class => Internationalized column title)
1469
- */
1470
- function admin_wftable_start($headers = false) {
1471
- echo "\n<table class='table table-bordered'>\n";
1472
- if ($headers)
1473
- $this->table_column_headers($headers);
1474
- else {
1475
- echo "\t<thead><tr>\n";
1476
- print_column_headers($this->plugin_page_hook);
1477
- echo "\t</tr></thead>\n";
1478
- echo "\t<tfoot><tr>\n";
1479
- print_column_headers($this->plugin_page_hook);
1480
- echo "\t</tr></tfoot>\n";
1481
- }
1482
- echo "\t<tbody>\n";
1483
- }
1484
-
1485
- /**
1486
- * Outputs a <tr> of <th scope="col"></th> tags based on an array of column headers.
1487
- *
1488
- * @since 2.1
1489
- *
1490
- * @param $headers Array of (CSS class => Internationalized column title)
1491
- */
1492
- function table_column_headers($headers) {
1493
- echo "\t<thead><tr>\n";
1494
- $mk = $this->get_module_key();
1495
- foreach ($headers as $class => $header) {
1496
- $class = is_numeric($class) ? '' : " class='su-$mk-$class su-$class'";
1497
- echo "\t\t<th scope='col'$class>$header</th>\n";
1498
- }
1499
- echo "\t</tr></thead>\n";
1500
- }
1501
-
1502
- /**
1503
- * Outputs <td> tags based on an array of cell data.
1504
- *
1505
- * @since 2.1
1506
- *
1507
- * @param $headers Array of (CSS class => Cell data)
1508
- */
1509
- function table_cells($cells) {
1510
-
1511
- if (count($this->get_admin_table_columns())) {
1512
- $columns = get_column_headers($this->plugin_page_hook);
1513
- $hidden = get_hidden_columns($this->plugin_page_hook);
1514
- foreach ( $columns as $column_name => $column_display_name ) {
1515
- $class = "class=\"$column_name column-$column_name\"";
1516
- $style = in_array($column_name, $hidden) ? ' style="display:none;"' : '';
1517
- echo "\t\t<td $class$style>".$cells[$column_name]."</td>\n";
1518
- }
1519
- } elseif (is_array($cells) && count($cells)) {
1520
- foreach ($cells as $class => $content) {
1521
- $class = is_numeric($class) ? '' : " class='su-$class'";
1522
- echo "\t\t<td$class>$content</td>\n";
1523
- }
1524
- }
1525
- }
1526
-
1527
- /**
1528
- * Outputs a <tr> tag with <td> children.
1529
- *
1530
- * @since 2.9
1531
- */
1532
- function table_row($cells, $id, $class) {
1533
- $mk = $this->get_module_key();
1534
- echo "\t<tr id='su-$mk-$id' class='su-$mk-$class'>\n";
1535
- $this->table_cells($cells);
1536
- echo "\t</tr>\n";
1537
- }
1538
-
1539
- /**
1540
- * Ends a "widefat" WordPress table.
1541
- *
1542
- * @since 1.8
1543
- */
1544
- function admin_wftable_end() {
1545
- echo "\t</tbody>\n</table>\n";
1546
- }
1547
-
1548
- /**
1549
- * Outputs the HTML that begins an admin form group.
1550
- *
1551
- * @since 1.5
1552
- *
1553
- * @param string $title The title of the group.
1554
- * @param bool $newtable Whether to open a new <table> element.
1555
- */
1556
- function admin_form_group_start($title, $newtable=true) {
1557
- echo "<div class='form-group'>\n<label class='col-sm-4 col-md-4 control-label'>$title</label><div class='col-sm-4 col-md-4'>\n";
1558
- }
1559
-
1560
- /**
1561
- * Outputs the HTML that ends an admin form group.
1562
- *
1563
- * @since 1.5
1564
- *
1565
- * @param bool $newtable Whether to close a <table> element.
1566
- */
1567
- function admin_form_group_end($newtable=true) {
1568
- echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
1569
- }
1570
-
1571
- function admin_form_indent_start() {
1572
- echo "<div class='form-group'><div class='col-md-12'>";
1573
- }
1574
-
1575
- function admin_form_indent_end() {
1576
- echo "</div></div>";
1577
- }
1578
-
1579
- /**
1580
- * Outputs a text block into an admin form.
1581
- *
1582
- * @since 1.5
1583
- *
1584
- * @param string $text
1585
- */
1586
- function textblock($text) {
1587
- echo "<div class='form-group su-admin-form-textblock'>\n<div class='col-md-12'>\n";
1588
- echo $text;
1589
- echo "\n</div>\n</div>\n";
1590
- }
1591
-
1592
- /**
1593
- * Outputs a group of checkboxes into an admin form, and saves the values into the database after form submission.
1594
- *
1595
- * @since 0.1
1596
- * @uses is_action()
1597
- * @uses update_setting()
1598
- * @uses get_module_key()
1599
- * @uses get_setting()
1600
- *
1601
- * @param array $checkboxes An array of checkboxes. (Field/setting IDs are the keys, and descriptions are the values.)
1602
- * @param mixed $grouptext The text to display in a table cell to the left of the one containing the checkboxes. Optional.
1603
- */
1604
- function checkboxes($checkboxes, $grouptext=false, $args=array()) {
1605
-
1606
- extract(wp_parse_args($args, array(
1607
- 'output_tr' => true
1608
- )));
1609
-
1610
- //Save checkbox settings after form submission
1611
- if ($this->is_action('update')) {
1612
- foreach ($checkboxes as $name => $desc) {
1613
- $new_value = isset($_POST[$name]) ? ($_POST[$name] == '1') : false;
1614
-
1615
- if (is_array($desc)) {
1616
- $disabled = isset($desc['disabled']) ? $desc['disabled'] : false;
1617
- $desc = isset($desc['description']) ? $desc['description'] : '';
1618
- } else {
1619
- $disabled = false;
1620
- }
1621
-
1622
- if (!$disabled)
1623
- $this->update_setting($name, $new_value);
1624
-
1625
- if (strpos($desc, '%d') !== false) {
1626
- $name .= '_value';
1627
- $this->update_setting($name, sustr::to_int($_POST[$name]));
1628
- }
1629
- }
1630
- }
1631
-
1632
- if ($grouptext)
1633
- $this->admin_form_group_start($grouptext, false);
1634
- elseif ($output_tr)
1635
- echo "<div class='form-group su-admin-form-checkbox'>\n<div class='col-md-12'>\n";
1636
-
1637
- if (is_array($checkboxes)) {
1638
- foreach ($checkboxes as $name => $desc) {
1639
-
1640
- if (is_array($desc)) {
1641
- $indent = isset($desc['indent']) ? $desc['indent'] : false;
1642
- $disabled = isset($desc['disabled']) ? $desc['disabled'] : false;
1643
- $checked = isset($desc['checked']) ? $desc['checked'] : null;
1644
- $desc = $desc['description'];
1645
- } else {
1646
- $indent = false;
1647
- $disabled = false;
1648
- $checked = null;
1649
- }
1650
-
1651
- register_setting($this->get_module_key(), $name, array('sustr', 'to_int'));
1652
- $name = su_esc_attr($name);
1653
-
1654
- if (strpos($desc, '%d') === false) {
1655
- $onclick = '';
1656
- } else {
1657
- $int_var_name = $name.'_value';
1658
- $int_var_value = sustr::to_int($this->get_setting($int_var_name));
1659
- if ($this->get_setting($name) === true) $sfdisabled = ''; else $sfdisabled = "readonly='readonly' ";
1660
- $desc = str_replace('%d', "</label><input name='$int_var_name' id='$int_var_name' class='form-control input-sm nowidth-input' type='text' value='$int_var_value' size='2' maxlength='3' $sfdisabled/><label for='$name'>", $desc);
1661
- $desc = str_replace("<label for='$name'></label>", '', $desc);
1662
- $onclick = " onclick=\"javascript:document.getElementById('$int_var_name').readOnly=!this.checked;\"";
1663
- }
1664
-
1665
- if ($indent) $labelclass = " class='su-indent'"; else $labelclass = '';
1666
- echo "<div class='checkbox'><label for='$name'$labelclass><input name='$name' id='$name' type='checkbox' value='1'";
1667
- if ($checked !== false && ($checked === true || $this->get_setting($name) === true)) echo " checked='checked'";
1668
- if ($disabled) echo " disabled='disabled'";
1669
- echo "$onclick /> $desc</label></div>\n";
1670
- }
1671
- }
1672
-
1673
- if ($grouptext) {
1674
- $this->admin_form_group_end(false);
1675
- } elseif ($output_tr) {
1676
- echo "</div>\n</div>\n";
1677
- }
1678
- }
1679
-
1680
- /**
1681
- * Outputs a single checkbox into an admin form and saves its value into the database after form submission.
1682
- *
1683
- * @since 1.5
1684
- * @uses checkboxes()
1685
- *
1686
- * @param string $id The field/setting ID.
1687
- * @param string $desc The checkbox's label.
1688
- * @param mixed $grouptext The text to display in a table cell to the left of the one containing the checkbox. Optional.
1689
- * @return string The HTML that would render the checkbox.
1690
- */
1691
- function checkbox($id, $desc, $grouptext = false, $args=array()) {
1692
- $this->checkboxes(array($id => $desc), $grouptext, $args);
1693
- }
1694
-
1695
- /**
1696
- * Outputs a set of radio buttons into an admin form and saves the set's value into the database after form submission.
1697
- *
1698
- * @since 1.5
1699
- * @uses is_action()
1700
- * @uses update_setting()
1701
- * @uses admin_form_group_start()
1702
- * @uses admin_form_group_end()
1703
- * @uses su_esc_attr()
1704
- * @uses get_setting()
1705
- *
1706
- * @param string $name The name of the set of radio buttons.
1707
- * @param array $values The keys of this array are the radio button values, and the array values are the label strings.
1708
- * @param string|false $grouptext The text to display in a table cell to the left of the one containing the radio buttons. Optional.
1709
- */
1710
- function radiobuttons($name, $values, $grouptext=false) {
1711
-
1712
- //Save radio button setting after form submission
1713
- if ($this->is_action('update') && isset($_POST[$name]))
1714
- $this->update_setting($name, $_POST[$name]);
1715
-
1716
- if ($grouptext)
1717
- $this->admin_form_group_start($grouptext, false);
1718
- else
1719
- echo "<tr valign='top' class='su-admin-form-radio'>\n<td colspan='2'>\n";
1720
-
1721
- if (is_array($values)) {
1722
-
1723
- register_setting($this->get_module_key(), $name);
1724
- $name = su_esc_attr($name);
1725
-
1726
- $first = true;
1727
- foreach ($values as $value => $desc) {
1728
-
1729
- $value = su_esc_attr($value);
1730
- $id = "{$name}_{$value}";
1731
-
1732
- $current = (strcmp($this->get_setting($name), $value) == 0);
1733
- $class = $first ? 'first' : ''; $first = false;
1734
- if ($current) $class .= ' current-setting';
1735
- $class = trim($class);
1736
- if ($class) $class = " class='$class'";
1737
-
1738
- extract($this->insert_subfield_textboxes($name, $desc));
1739
-
1740
- echo "<div class='radio'><label for='$id'$class><input name='$name' id='$id' type='radio' value='$value'";
1741
- if ($current) echo " checked='checked'";
1742
- echo " /> $label";
1743
-
1744
- if (!sustr::has($label, '</label>')) echo '</label>';
1745
- echo "</div>\n";
1746
- }
1747
- }
1748
-
1749
- if ($grouptext)
1750
- $this->admin_form_group_end(false);
1751
- }
1752
-
1753
- /**
1754
- * Outputs a dropdown into an admin form and saves the dropdown's value into the database after form submission.
1755
- *
1756
- * @since 3.7
1757
- * @uses is_action()
1758
- * @uses update_setting()
1759
- * @uses admin_form_group_start()
1760
- * @uses admin_form_group_end()
1761
- * @uses su_esc_attr()
1762
- * @uses get_setting()
1763
- *
1764
- * @param string $name The name of the setting which the dropdown is supposed to set.
1765
- * @param array $values The keys of this array are the possible dropdown option values, and the array values are the option label strings.
1766
- * @param string|false $grouptext The text to display in a table cell to the left of the one containing the dropdown. Optional.
1767
- * @param string $text A printf-style format string in which "%s" is replaced with the dropdown. Use this to put text before or after the dropdown.
1768
- */
1769
- function dropdown($name, $values, $grouptext=false, $text='%s', $args=array()) {
1770
-
1771
- $in_table = isset($args['in_table']) ? $args['in_table'] : true;
1772
-
1773
- //Save dropdown setting after form submission
1774
- if ($this->is_action('update') && isset($_POST[$name]))
1775
- $this->update_setting($name, $_POST[$name]);
1776
-
1777
- if ($grouptext)
1778
- $this->admin_form_group_start($grouptext, false);
1779
- elseif ($in_table)
1780
- echo "<div class='form-group su-admin-form-dropdown'>\n<div class='col-sm-4 col-md-4'>\n";
1781
-
1782
- if (is_array($values)) {
1783
-
1784
- register_setting($this->get_module_key(), $name);
1785
-
1786
- $name = su_esc_attr($name);
1787
- $dropdown = "<select name='$name' id='$name'>\n"
1788
- . suhtml::option_tags($values, $this->get_setting($name))
1789
- . "</select>";
1790
- printf($text, $dropdown);
1791
- }
1792
-
1793
- if ($grouptext)
1794
- $this->admin_form_group_end();
1795
- elseif ($in_table)
1796
- echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
1797
- }
1798
-
1799
- /**
1800
- * @since 3.0
1801
- */
1802
- function insert_subfield_textboxes($name, $label, $enabled = true) {
1803
-
1804
- $pattern = '/%(d|s)({([a-z0-9_-]+)})?/';
1805
-
1806
- if (preg_match($pattern, $label, $matches)) {
1807
- $is_int_field = ($matches[1] == 'd');
1808
- $sfname = $name.'_value';
1809
-
1810
- if (isset($matches[3]))
1811
- $sfname = $matches[3];
1812
-
1813
- if ($this->is_action('update'))
1814
- $sfvalue = stripslashes($_POST[$sfname]);
1815
- else
1816
- $sfvalue = $this->get_setting($sfname);
1817
-
1818
- if ($is_int_field)
1819
- $sfvalue = sustr::to_int($sfvalue);
1820
-
1821
- if ($this->is_action('update'))
1822
- $this->update_setting($sfname, $sfvalue);
1823
-
1824
- if ($enabled) $disabled = ''; else $disabled = " readonly='readonly'";
1825
-
1826
- $esfvalue = su_esc_attr($sfvalue);
1827
- $field_html = "</label><input class='textbox subfield form-control input-sm' name='$sfname' id='$sfname' type='text' value='$esfvalue'$disabled";
1828
- if ($is_int_field) $field_html .= " size='2' maxlength='3'";
1829
- $field_html .= " /><label for='$name'>";
1830
-
1831
- $label = preg_replace($pattern, $field_html, $label);
1832
- $label = preg_replace("@<label for='$name'>$@", '', $label);
1833
-
1834
- $onclick = " onclick=\"javascript:document.getElementById('$sfname').readOnly=!this.checked;\"";
1835
- } else
1836
- $onclick = '';
1837
-
1838
- return compact('label', 'onclick');
1839
- }
1840
-
1841
- /**
1842
- * Outputs a group of textboxes into an admin form, and saves the values into the database after form submission.
1843
- * Can also display a "Reset" link next to each textbox that reverts its value to a specified default.
1844
- *
1845
- * @since 0.1
1846
- * @uses is_action()
1847
- * @uses update_setting()
1848
- * @uses get_module_key()
1849
- * @uses get_setting()
1850
- *
1851
- * @param array $textboxes An array of textboxes. (Field/setting IDs are the keys, and descriptions are the values.)
1852
- * @param array $defaults An array of default textbox values that trigger "Reset" links. (The field/setting ID is the key, and the default value is the value.) Optional.
1853
- * @param mixed $grouptext The text to display in a table cell to the left of the one containing the textboxes. Optional.
1854
- */
1855
- function textboxes($textboxes, $defaults=array(), $grouptext=false, $args=array(), $textbox_args=array()) {
1856
-
1857
- $is_tree_parent = isset($args['is_tree_parent']) ? $args['is_tree_parent'] : false;
1858
- $is_ec_tree = isset($args['is_ec_tree']) ? $args['is_ec_tree'] : false;
1859
- $tree_level = isset($args['tree_level']) ? $args['tree_level'] : false;
1860
- $disabled = isset($args['disabled']) ? $args['disabled'] : false;
1861
- $in_table = isset($args['in_table']) ? $args['in_table'] : true;
1862
- $help_text = isset($args['help_text']) ? $args['help_text'] : false;
1863
- $callout = isset($args['callout']) ? $args['callout'] : false;
1864
-
1865
- if (!$disabled && $this->is_action('update')) {
1866
- foreach ($textboxes as $id => $title) {
1867
- if (isset($_POST[$id]))
1868
- $this->update_setting($id, stripslashes($_POST[$id]));
1869
- }
1870
- }
1871
-
1872
- $indentattrs = $indenttoggle = $hidden = '';
1873
- if ($tree_level !== false) {
1874
- $indentattrs = " class='su-indent su-indent-level-{$tree_level}'";
1875
- if ($is_ec_tree) {
1876
- if ($is_tree_parent)
1877
- $indenttoggle = "<span class='su-child-fields-toggle'>+</span> ";
1878
- else
1879
- $indenttoggle = "<span class='su-child-fields-toggle-filler'> </span> ";
1880
-
1881
- if ($tree_level > 1)
1882
- $hidden = " style='display: none;'";
1883
- }
1884
- }
1885
-
1886
- if ($grouptext) $this->admin_form_group_start($grouptext, false);
1887
-
1888
- foreach ($textboxes as $id => $title) {
1889
-
1890
- $before = isset($textbox_args[$id]['before']) ? $textbox_args[$id]['before'] : '';
1891
- $after = isset($textbox_args[$id]['after']) ? $textbox_args[$id]['after'] : '';
1892
- $placeholder = isset($textbox_args[$id]['placeholder']) ? $textbox_args[$id]['placeholder'] : '';
1893
-
1894
- register_setting($this->get_module_key(), $id);
1895
- $value = su_esc_editable_html($this->get_setting($id));
1896
- $id = su_esc_attr($id);
1897
- $resetmessage = su_esc_attr(__('Are you sure you want to replace the textbox contents with this default value?', 'seo-ultimate'));
1898
-
1899
- if ($callout)
1900
- echo "<div class='bs-callout bs-callout-grey'><h4>$callout</h4></div>\n";
1901
-
1902
- if ($grouptext)
1903
- echo "<div class='form-group'><label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n<div class='col-sm-4 col-md-4'>\n";
1904
- elseif ($in_table && strpos($title, '</a>') === false)
1905
- echo "<div class='form-group'$indentattrs$hidden>\n<label class='col-sm-4 col-md-4 control-label' for='$id'><span class='su-field-label-text'>$title</span></label>\n<div class='col-sm-4 col-md-4'>\n";
1906
- elseif ($in_table)
1907
- echo "<div class='form-group'$indentattrs$hidden>\n<label class='col-sm-4 col-md-4 control-label' for='$id'><span class='su-field-label-text'>$title</span></label>\n<div class='col-sm-4 col-md-4'>\n";
1908
-
1909
- echo $before;
1910
-
1911
- echo "<input name='$id' id='$id' type='text' value='$value' class='form-control input-sm regular-text' ";
1912
-
1913
- if ($placeholder) {
1914
- $a_placeholder = su_esc_attr($placeholder);
1915
- echo "placeholder='$placeholder' ";
1916
- }
1917
-
1918
- if ($disabled)
1919
- echo "disabled='disabled' />";
1920
- elseif (isset($defaults[$id])) {
1921
- $default = su_esc_editable_html($defaults[$id]);
1922
- echo "onkeyup=\"javascript:su_textbox_value_changed(this, '$default', '{$id}_reset')\" />";
1923
- echo "&nbsp;<a href=\"#\" id=\"{$id}_reset\" onclick=\"javascript:su_reset_textbox('$id', '$default', '$resetmessage', this); return false;\"";
1924
- if ($default == $value) echo ' class="hidden"';
1925
- echo ">";
1926
- _e('Reset', 'seo-ultimate');
1927
- echo "</a>";
1928
-
1929
- if (isset($args['open_url_value_link']))
1930
- echo ' |';
1931
- } else {
1932
- echo "/>";
1933
- }
1934
-
1935
- if (isset($args['open_url_value_link'])) {
1936
- echo " <a href='#' onclick=\"javascript:window.open(document.getElementById('$id').value);return false;\">";
1937
- echo su_esc_html($args['open_url_value_link']);
1938
- echo '</a>';
1939
- }
1940
-
1941
- echo $after;
1942
-
1943
- if ($grouptext)
1944
- echo "</div>\n";
1945
- elseif ($in_table)
1946
- echo "</div>\n";
1947
-
1948
- if ($help_text)
1949
- echo "<div class='col-sm-4 col-md-4'>$help_text</div>\n</div>\n";
1950
- else
1951
- echo "<div class='col-sm-4 col-md-4'></div>\n</div>\n";
1952
- }
1953
-
1954
- if ($grouptext) $this->admin_form_group_end(false);
1955
- }
1956
-
1957
- /**
1958
- * Outputs a single textbox into an admin form and saves its value into the database after form submission.
1959
- *
1960
- * @since 0.1
1961
- * @uses textboxes()
1962
- *
1963
- * @param string $id The field/setting ID.
1964
- * @param string $title The label of the HTML element.
1965
- * @param string|false $default The default textbox value. Setting this will trigger a "Reset" link. Optional.
1966
- * @return string The HTML that would render the textbox.
1967
- */
1968
- function textbox($id, $title, $default=false, $grouptext=false, $args=array(), $textbox_args=array()) {
1969
- if ($default === false) $default = array(); else $default = array($id => $default);
1970
- $this->textboxes(array($id => $title), $default, $grouptext, $args, array($id => $textbox_args));
1971
- }
1972
-
1973
- /**
1974
- * Outputs a group of textareas into an admin form, and saves the values into the database after form submission.
1975
- *
1976
- * @since 0.1
1977
- * @uses is_action()
1978
- * @uses update_setting()
1979
- * @uses get_module_key()
1980
- * @uses get_setting()
1981
- *
1982
- * @param array $textareas An array of textareas. (Field/setting IDs are the keys, and descriptions are the values.)
1983
- * @param int $rows The value of the textareas' rows attribute.
1984
- * @param int $cols The value of the textareas' cols attribute.
1985
- */
1986
- function textareas($textareas, $rows = 5, $cols = 30, $args=array()) {
1987
-
1988
- $disabled = isset($args['disabled']) ? $args['disabled'] : false;
1989
-
1990
- if (!$disabled && $this->is_action('update')) {
1991
- foreach ($textareas as $id => $title) {
1992
- if (isset($_POST[$id]))
1993
- $this->update_setting($id, stripslashes($_POST[$id]));
1994
- }
1995
- }
1996
-
1997
- foreach ($textareas as $id => $title) {
1998
- register_setting($this->get_module_key(), $id);
1999
- $value = su_esc_editable_html($this->get_setting($id));
2000
- $id = su_esc_attr($id);
2001
-
2002
- echo "<div class='form-group'>\n";
2003
- if ($title) echo "<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n";
2004
- echo "<div class='col-sm-4 col-md-4'>";
2005
- echo "<textarea name='$id' id='$id' type='text' class='form-control regular-text' cols='$cols' rows='$rows'";
2006
- if ($disabled) echo " disabled='disabled'";
2007
- echo ">$value</textarea>";
2008
- echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2009
- }
2010
- }
2011
-
2012
- /**
2013
- * Outputs a single textarea into an admin form and saves its value into the database after form submission.
2014
- *
2015
- * @since 0.1
2016
- * @uses textareas()
2017
- *
2018
- * @param string $id The field/setting ID.
2019
- * @param string $title The label of the HTML element.
2020
- * @param int $rows The value of the textarea's rows attribute.
2021
- * @param int $cols The value of the textarea's cols attribute.
2022
- * @return string The HTML that would render the textarea.
2023
- */
2024
- function textarea($id, $title = '', $rows = 5, $cols = 30) {
2025
- $this->textareas(array($id => $title), $rows, $cols);
2026
- }
2027
-
2028
- /**
2029
- * @since 7.3
2030
- */
2031
- function jlsuggest_boxes($jls_boxes) {
2032
-
2033
- if ($this->is_action('update')) {
2034
- foreach ($jls_boxes as $jls_box) {
2035
-
2036
- if (!isset($jls_box['id']))
2037
- continue;
2038
-
2039
- $id = $jls_box['id'];
2040
-
2041
- if (isset($_POST[$id]))
2042
- $this->update_setting($id, stripslashes($_POST[$id]));
2043
- }
2044
- }
2045
-
2046
- foreach ($jls_boxes as $jls_box) {
2047
-
2048
- if (!isset($jls_box['id']))
2049
- continue;
2050
-
2051
- $jls_box = wp_parse_args($jls_box, array(
2052
- 'title' => ''
2053
- , 'params' => ''
2054
- ));
2055
-
2056
- extract($jls_box, EXTR_SKIP);
2057
-
2058
- register_setting($this->get_module_key(), $id);
2059
-
2060
- echo "<div class='form-group'>\n";
2061
- if ($title) echo "<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n";
2062
- echo "<div class='col-sm-4 col-md-4'>";
2063
- echo $this->get_jlsuggest_box($id, $this->get_setting($id), $params);
2064
- echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2065
- }
2066
- }
2067
-
2068
- /**
2069
- * @since 7.3
2070
- */
2071
- function jlsuggest_box($id, $title, $params='') {
2072
- $this->jlsuggest_boxes(array(compact('id', 'title', 'params')));
2073
- }
2074
- /**
2075
- * @since 7.6.3
2076
- */
2077
- function medialib_boxes($media_boxes) {
2078
-
2079
- if ($this->is_action('update')) {
2080
- foreach ($media_boxes as $media_box) {
2081
-
2082
- if (!isset($media_box['id']))
2083
- continue;
2084
-
2085
- $id = $media_box['id'];
2086
-
2087
- if (isset($_POST[$id]))
2088
- $this->update_setting($id, stripslashes($_POST[$id]));
2089
- }
2090
- }
2091
-
2092
- foreach ($media_boxes as $media_box) {
2093
-
2094
- if (!isset($media_box['id']))
2095
- continue;
2096
-
2097
- $media_box = wp_parse_args($media_box, array(
2098
- 'title' => ''
2099
- , 'params' => ''
2100
- ));
2101
-
2102
- extract($media_box, EXTR_SKIP);
2103
-
2104
- register_setting($this->get_module_key(), $id);
2105
-
2106
- echo "<div class='form-group'>\n";
2107
- if ($title) echo "<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n";
2108
- echo "<div class='col-sm-4 col-md-4'>";
2109
- echo "<div class='input-group'>
2110
- <input id='".su_esc_attr($id)."' name='".su_esc_attr($id)."' type='text' class='wpu-image form-control' size='40' value='".$this->get_setting($id)."'>
2111
- <span class='input-group-btn'>
2112
- <span class='btn btn-custom btn-file wpu-media-upload'>
2113
- <i class='fa fa-upload'></i> Upload Image <input type='file'>
2114
- </span>
2115
- </span>
2116
- </div>";
2117
- echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2118
- }
2119
- }
2120
-
2121
- /**
2122
- * @since 7.6.3
2123
- */
2124
- function medialib_box($id, $title, $params='') {
2125
- $this->medialib_boxes(array(compact('id', 'title', 'params')));
2126
- }
2127
-
2128
- /********** ADMIN SECURITY FUNCTIONS **********/
2129
-
2130
- /**
2131
- * Determines if a particular nonce-secured admin action is being executed.
2132
- *
2133
- * @since 0.1
2134
- * @uses SEO_Ultimate::key_to_hook()
2135
- * @uses get_module_key()
2136
- * @uses nonce_validates()
2137
- *
2138
- * @param string $action The name of the action to check.
2139
- * @return bool Whether or not the action is being executed.
2140
- */
2141
- function is_action($action) {
2142
- if (!isset($_GET['object']) || !($object = $_GET['object'])) $object = false;
2143
- return (
2144
- !empty($_GET['page'])
2145
- && (
2146
- ( strcasecmp($_GET['page'], $this->plugin->key_to_hook($this->get_module_key())) == 0 ) //Is $this module being shown?
2147
- || ( strlen($this->get_parent_module()) && strcasecmp($_GET['page'], $this->plugin->key_to_hook($this->get_parent_module())) == 0) //Is the parent module being shown?
2148
- )
2149
- && (
2150
- (!empty($_GET['action']) && $_GET['action'] == $action)
2151
- || (!empty($_POST['action']) && $_POST['action'] == $action)
2152
- ) //Is this $action being executed?
2153
- && $this->nonce_validates($action, $object) //Is the nonce valid?
2154
- );
2155
- }
2156
-
2157
- /**
2158
- * Determines whether a nonce is valid.
2159
- *
2160
- * @since 0.1
2161
- * @uses get_nonce_handle()
2162
- *
2163
- * @param string $action The name of the action.
2164
- * @param mixed $id The ID of the object being acted upon. Optional.
2165
- * @return bool Whether or not the nonce is valid.
2166
- */
2167
- function nonce_validates($action, $id = false) {
2168
- return check_admin_referer($this->get_nonce_handle($action, $id));
2169
- }
2170
-
2171
- /**
2172
- * Generates a unique name for a nonce.
2173
- *
2174
- * @since 0.1
2175
- * @uses get_parent_module()
2176
- * @uses get_module_key()
2177
- * @uses SU_PLUGIN_NAME
2178
- *
2179
- * @param string $action The name of the action.
2180
- * @param mixed $id The ID of the object being acted upon. Optional.
2181
- * @return The handle to use for the nonce.
2182
- */
2183
- function get_nonce_handle($action, $id = false) {
2184
-
2185
- $key = $this->get_parent_module();
2186
- if (!$key || !$this->plugin->module_exists($key)) $key = $this->get_module_key();
2187
-
2188
- $hook = $this->plugin->key_to_hook($key);
2189
-
2190
- if (strcmp($action, 'update') == 0) {
2191
- //We use the settings_fields() function, which outputs a nonce in this particular format.
2192
- return "$hook-options";
2193
- } else {
2194
- if ($id) $id = '-'.md5($id); else $id = '';
2195
- $handle = SU_PLUGIN_NAME."-$hook-$action$id";
2196
- return strtolower(str_replace(' ', '-', $handle));
2197
- }
2198
- }
2199
-
2200
- /**
2201
- * Returns a GET-action URL with an appended nonce.
2202
- *
2203
- * @since 0.1
2204
- * @uses get_module_key()
2205
- * @uses get_nonce_handle()
2206
- *
2207
- * @param string $action The name of the action.
2208
- * @param mixed $id The ID of the object being acted upon. Optional.
2209
- * @return The URL to use in an <a> tag.
2210
- */
2211
- function get_nonce_url($action, $object=false) {
2212
- $action = urlencode($action);
2213
- if ($object) $objectqs = '&object='.urlencode($object); else $objectqs = '';
2214
-
2215
- $hook = $this->plugin->key_to_hook($this->get_module_or_parent_key());
2216
-
2217
- //We don't need to escape ampersands since wp_nonce_url will do that for us
2218
- return wp_nonce_url("?page=$hook&action=$action$objectqs",
2219
- $this->get_nonce_handle($action, $object));
2220
- }
2221
-
2222
-
2223
- /********** ADMIN MESSAGE FUNCTIONS **********/
2224
-
2225
- /**
2226
- * Print a message (and any previously-queued messages) right away.
2227
- *
2228
- * @since 0.1
2229
- * @uses queue_message()
2230
- * @uses print_messages()
2231
- *
2232
- * @param string $type The message's type. Valid values are success, error, warning, and info.
2233
- * @param string $message The message text.
2234
- */
2235
- function print_message($type, $message) {
2236
- $this->queue_message($type, $message);
2237
- $this->print_messages();
2238
- }
2239
-
2240
- /**
2241
- * Adds a message to the queue.
2242
- *
2243
- * @since 0.1
2244
- * @uses $messages
2245
- *
2246
- * @param string $type The message's type. Valid values are success, error, warning, and info.
2247
- * @param string $message The message text.
2248
- */
2249
- function queue_message($type, $message) {
2250
- $this->messages[$type][] = $message;
2251
- }
2252
-
2253
- /**
2254
- * Prints all queued messages and flushes the queue.
2255
- *
2256
- * @since 0.1
2257
- * @uses $messages
2258
- */
2259
- function print_messages() {
2260
- foreach ($this->messages as $type => $messages) {
2261
- $messages = implode('<br />', $messages);
2262
- if ($messages) {
2263
- $type = su_esc_attr($type);
2264
- echo "<div class='su-message'><p class='su-$type'>$messages</p></div>\n";
2265
- }
2266
- }
2267
-
2268
- $this->messages = array();
2269
- }
2270
-
2271
- /**
2272
- * Prints a mini-style message.
2273
- *
2274
- * @since 2.1
2275
- */
2276
- function print_mini_message($type, $message) {
2277
- $type = su_esc_attr($type);
2278
- echo "<div class='su-status su-$type'>$message</div>";
2279
- }
2280
-
2281
- /********** ADMIN META FUNCTIONS **********/
2282
-
2283
- /**
2284
- * Gets a specified meta value of the current post (i.e. the post currently being edited in the admin,
2285
- * the post being shown, the post now in the loop, or the post with specified ID).
2286
- *
2287
- * @since 0.1
2288
- *
2289
- * @param string $key The meta key to fetch.
2290
- * @param mixed $id The ID number of the post/page.
2291
- * @return string The meta value requested.
2292
- */
2293
- function get_postmeta($key, $id=false) {
2294
-
2295
- if (!$id) {
2296
- //This code is different from suwp::get_post_id();
2297
- if (is_admin()) {
2298
- $id = empty($_REQUEST['post']) ? false : intval($_REQUEST['post']);
2299
- global $post;
2300
- } elseif (in_the_loop()) {
2301
- $id = intval(get_the_ID());
2302
- global $post;
2303
- } elseif (is_singular()) {
2304
- global $wp_query;
2305
- $id = $wp_query->get_queried_object_id();
2306
- $post = $wp_query->get_queried_object();
2307
- }
2308
- }
2309
-
2310
- if ($id) {
2311
-
2312
- if (isset($post) && $post)
2313
- $_post = $post;
2314
- else
2315
- $_post = get_post($id);
2316
-
2317
- $value = get_post_meta($id, "_su_$key", true);
2318
- $value = apply_filters("su_get_postmeta", $value, $key, $_post);
2319
- $value = apply_filters("su_get_postmeta-$key", $value, $key, $_post);
2320
- } else
2321
- $value = '';
2322
-
2323
- return $value;
2324
- }
2325
-
2326
- /**
2327
- * Generates the HTML for multiple post meta textboxes.
2328
- *
2329
- * @since 0.1
2330
- * @uses get_postmeta()
2331
- *
2332
- * @param array $textboxes An array of textboxes. (Field/setting IDs are the keys, and descriptions are the values.)
2333
- * @return string The HTML that would render the textboxes.
2334
- */
2335
- function get_postmeta_textboxes($textboxes, $textbox_args=array(), $grouptext=false) {
2336
-
2337
- $html = '';
2338
-
2339
- if ($grouptext) {
2340
- $h_grouptext = esc_html($grouptext);
2341
- $html = "<div class='form-group su textbox'>\n<h4 class='col-sm-4 col-md-4 control-label'>$h_grouptext</h4>\n<div class='col-sm-4 col-md-4'></div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2342
- }
2343
-
2344
- foreach ($textboxes as $id => $title) {
2345
-
2346
- $type = isset($textbox_args[$id]['type']) ? $textbox_args[$id]['type'] : 'text';
2347
- $input_clss = ($type == 'text') ? 'input-sm ' : '';
2348
-
2349
- register_setting('seo-ultimate', $id);
2350
- $value = su_esc_editable_html($this->get_postmeta($id));
2351
- $id = "_su_".su_esc_attr($id);
2352
-
2353
- $e_title = su_esc_attr($title);
2354
-
2355
- $html = "<div class='form-group su textbox'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n<div class='col-sm-4 col-md-4'><input name='$id' id='$id' type='$type' value='$value' class='"
2356
- . $input_clss."form-control regular-text' tabindex='2' />\n"
2357
- . "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2358
- }
2359
-
2360
- if ($grouptext) {
2361
- $h_grouptext = esc_html($grouptext);
2362
- //$html .= "</table></td>\n</tr>\n";
2363
- }
2364
-
2365
- return $html;
2366
- }
2367
-
2368
- /**
2369
- * Generates the HTML for a single post meta textbox.
2370
- *
2371
- * @since 0.1
2372
- * @uses get_postmeta_textboxes()
2373
- *
2374
- * @param string $id The ID of the HTML element.
2375
- * @param string $title The label of the HTML element.
2376
- * @return string The HTML that would render the textbox.
2377
- */
2378
- function get_postmeta_textbox($id, $title, $args=array()) {
2379
- return $this->get_postmeta_textboxes(array($id => $title), array($id => $args));
2380
- }
2381
-
2382
- /**
2383
- * Generates the HTML for multiple post meta textareas.
2384
- *
2385
- * @since 3.9
2386
- * @uses get_postmeta()
2387
- *
2388
- * @param array $textareas An array of textareas. (Field/setting IDs are the keys, and descriptions are the values.)
2389
- * @return string The HTML that would render the textareas.
2390
- */
2391
- function get_postmeta_textareas($textareas) {
2392
-
2393
- $html = '';
2394
-
2395
- foreach ($textareas as $id => $title) {
2396
-
2397
- register_setting('seo-ultimate', $id);
2398
- $value = su_esc_editable_html($this->get_postmeta($id));
2399
- $id = "_su_".su_esc_attr($id);
2400
-
2401
- $html = "<div class='form-group su textarea'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n<div class='col-sm-4 col-md-4'><textarea name='$id' id='$id' class='form-control regular-text' tabindex='2' cols='60' rows='3'>$value</textarea>\n"
2402
- ."</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2403
- }
2404
-
2405
- return $html;
2406
- }
2407
-
2408
- /**
2409
- * Generates the HTML for a single post meta textarea.
2410
- *
2411
- * @since 3.9
2412
- * @uses get_postmeta_textareas()
2413
- *
2414
- * @param string $id The ID of the HTML element.
2415
- * @param string $title The label of the HTML element.
2416
- * @return string The HTML that would render the textarea.
2417
- */
2418
- function get_postmeta_textarea($id, $title) {
2419
- return $this->get_postmeta_textareas(array($id => $title));
2420
- }
2421
-
2422
- /**
2423
- * Generates the HTML for a group of post meta checkboxes.
2424
- *
2425
- * @since 0.1
2426
- * @uses get_module_key()
2427
- * @uses get_postmeta()
2428
- *
2429
- * @param array $checkboxes An array of checkboxes. (Field/setting IDs are the keys, and descriptions are the values.)
2430
- * @param string $grouptext The text to display in a table cell to the left of the one containing the checkboxes.
2431
- */
2432
- function get_postmeta_checkboxes($checkboxes, $grouptext) {
2433
-
2434
- $valign = (is_array($checkboxes) && count($checkboxes) > 1) ? 'top' : 'middle';
2435
- $html = "<div class='form-group su checkboxes'>\n<label class='col-sm-4 col-md-4 control-label'>$grouptext</label>\n<div class='col-sm-4 col-md-4'>\n";
2436
-
2437
- if (is_array($checkboxes)) {
2438
- foreach ($checkboxes as $name => $desc) {
2439
-
2440
- register_setting('seo-ultimate', $name);
2441
- $checked = ($this->get_postmeta($name) == 1);
2442
- $name = "_su_".su_esc_attr($name);
2443
-
2444
- $html .= "<div class='checkbox'><label for='$name'><input name='$name' id='$name' type='checkbox' tabindex='2' value='1'";
2445
- if ($checked) $html .= " checked='checked'";
2446
- $html .= " /> $desc</label></div>\n";
2447
- }
2448
- }
2449
-
2450
- $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2451
-
2452
- return $html;
2453
- }
2454
-
2455
- /**
2456
- * Generates the HTML for a single post meta checkbox.
2457
- *
2458
- * @since 0.1
2459
- * @uses get_postmeta_checkboxes()
2460
- *
2461
- * @param string $id The ID of the HTML element.
2462
- * @param string $title The label of the HTML element.
2463
- * @param string $grouptext The text to display in a table cell to the left of the one containing the checkboxes.
2464
- * @return string The HTML that would render the textbox.
2465
- */
2466
- function get_postmeta_checkbox($id, $title, $grouptext) {
2467
- return $this->get_postmeta_checkboxes(array($id => $title), $grouptext);
2468
- }
2469
-
2470
- /**
2471
- * Generates the HTML for a single <select> post meta dropdown.
2472
- *
2473
- * @since 2.5
2474
- * @uses get_module_key()
2475
- * @uses get_postmeta()
2476
- *
2477
- * @param string $name The name of the <select> element.
2478
- * @param array $options An array of options, where the array keys are the <option> values and the array values are the labels (<option> contents).
2479
- * @param string $grouptext The text to display in a table cell to the left of the one containing the dropdown.
2480
- * @return string $html
2481
- */
2482
- function get_postmeta_dropdown($name, $options, $grouptext) {
2483
-
2484
- register_setting('seo-ultimate', $name);
2485
- $current = $this->get_postmeta($name);
2486
- if ($current === '') {
2487
- $current = reset($options);
2488
- }
2489
- $name = "_su_".su_esc_attr($name);
2490
-
2491
- $html = "<div class='form-group su dropdown'>\n<label class='col-sm-4 col-md-4 control-label' for='$name'>$grouptext</label>\n<div class='col-sm-4 col-md-4'>\n";
2492
- $html .= "<select name='$name' id='$name' onchange='javascript:su_toggle_select_children(this)'>\n";
2493
- $html .= suhtml::option_tags($options, $current);
2494
- $html .= "</select>\n";
2495
- $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'></div>\n</div>\n";
2496
-
2497
- return $html;
2498
- }
2499
-
2500
- /**
2501
- * Generates the HTML for multiple post meta JLSuggest boxes.
2502
- *
2503
- * @since 7.3
2504
- *
2505
- * @param array $jls_boxes An array of JLSuggest boxes. (Field/setting IDs are the keys, and descriptions are the values.)
2506
- * @return string The HTML for the JLSuggest boxes.
2507
- */
2508
- function get_postmeta_jlsuggest_boxes($jls_boxes) {
2509
-
2510
- $html = '';
2511
-
2512
- foreach ($jls_boxes as $jls_box) {
2513
-
2514
- if (!isset($jls_box['id']) || !isset($jls_box['title']))
2515
- continue;
2516
-
2517
- $id = $jls_box['id'];
2518
- $title = $jls_box['title'];
2519
- $params = isset($jls_box['params']) ? $jls_box['params'] : false;
2520
-
2521
- register_setting('seo-ultimate', $id);
2522
- $value = su_esc_editable_html($this->get_postmeta($id));
2523
- $id = "_su_".su_esc_attr($id);
2524
-
2525
- $html .= "<div class='form-group su jlsuggestbox'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n"
2526
- ."<div class='col-sm-4 col-md-4 su'>";
2527
- $html .= $this->get_jlsuggest_box($id, $value, $params);
2528
- $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2529
- }
2530
-
2531
- return $html;
2532
- }
2533
-
2534
- /**
2535
- * Generates the HTML for a single post meta JLSuggest box.
2536
- *
2537
- * @since 7.3
2538
- * @uses get_postmeta_jlsuggest_boxes()
2539
- *
2540
- * @param string $id The ID of the HTML element.
2541
- * @param string $title The label of the HTML element.
2542
- * @param string $params The value of the su:params attribute of the JLSuggest box (optional).
2543
- * @return string The HTML that would render the JLSuggest box.
2544
- */
2545
- function get_postmeta_jlsuggest_box($id, $title, $params=false) {
2546
- $jls_box = compact('id', 'title', 'params');
2547
- return $this->get_postmeta_jlsuggest_boxes(array($jls_box));
2548
- }
2549
-
2550
- /**
2551
- * Generates the HTML for multiple post meta mediaupload boxes.
2552
- *
2553
- * @since 7.6.3
2554
- *
2555
- * @param array $media_boxes An array of mediaupload boxes. (Field/setting IDs are the keys, and descriptions are the values.)
2556
- * @return string The HTML for the mediaupload boxes.
2557
- */
2558
- function get_postmeta_medialib_boxes($media_boxes) {
2559
-
2560
- $html = '';
2561
-
2562
- foreach ($media_boxes as $media_box) {
2563
-
2564
- if (!isset($media_box['id']) || !isset($media_box['title']))
2565
- continue;
2566
-
2567
- $id = $media_box['id'];
2568
- $title = $media_box['title'];
2569
-
2570
- register_setting('seo-ultimate', $id);
2571
- $value = su_esc_editable_html($this->get_postmeta($id));
2572
- $id = "_su_".su_esc_attr($id);
2573
-
2574
- $html .= "<div class='form-group su'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n"
2575
- ."<div class='col-sm-4 col-md-4 su'>";
2576
- $html .= "<div class='input-group'>
2577
- <input id='".su_esc_attr($id)."' name='".su_esc_attr($id)."' type='text' class='wpu-image form-control' size='40' value='".$value."'>
2578
- <span class='input-group-btn'>
2579
- <span class='btn btn-custom btn-file wpu-media-upload'>
2580
- <i class='fa fa-upload'></i> Upload Image <input type='file'>
2581
- </span>
2582
- </span>
2583
- </div>";
2584
- $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2585
- }
2586
-
2587
- return $html;
2588
- }
2589
-
2590
- /**
2591
- * Generates the HTML for a single post meta mediaupload box.
2592
- *
2593
- * @since 7.6.3
2594
- * @uses get_postmeta_medialib_boxes()
2595
- *
2596
- * @param string $id The ID of the HTML element.
2597
- * @param string $title The label of the HTML element.
2598
- * @return string The HTML that would render the mediaupload box.
2599
- */
2600
- function get_postmeta_medialib_box($id, $title) {
2601
- $media_box = compact('id', 'title');
2602
- return $this->get_postmeta_medialib_boxes(array($media_box));
2603
- }
2604
-
2605
- /**
2606
- * Turns a <tr> into a post meta subsection.
2607
- *
2608
- * @since 2.5
2609
- * @uses get_postmeta
2610
- *
2611
- * @param string $field
2612
- * @param string $value
2613
- * @param string $html
2614
- * @return string $html
2615
- */
2616
- function get_postmeta_subsection($field, $value, $html) {
2617
- $hidden = ($this->get_postmeta($field) == $value) ? '' : ' hidden';
2618
-
2619
- $field = su_esc_attr($field);
2620
- $value = su_esc_attr($value);
2621
- $html = str_replace("<div class='form-group ", "<div class='form-group su_{$field}_{$value}_subsection$hidden ", $html);
2622
- return $html;
2623
- }
2624
-
2625
- /**
2626
- * Gets a specified meta value of the current term.
2627
- *
2628
- * @since 5.4
2629
- *
2630
- * @param string $key The database setting where the metadata is stored. The function will add a "taxonomy_" prefix.
2631
- * @param mixed $id The ID number of the post/page.
2632
- * @return string The meta value requested.
2633
- */
2634
- function get_termmeta($key, $id=false, $module=false) {
2635
-
2636
- global $wp_query;
2637
-
2638
- if (!$id && suwp::is_tax())
2639
- $id = $wp_query->get_queried_object_id();
2640
-
2641
- if (!$id)
2642
- return null;
2643
-
2644
- $tax_meta = $this->get_setting(sustr::startwith($key, 'taxonomy_'), array(), $module);
2645
-
2646
- if (is_array($tax_meta) && isset($tax_meta[$id]))
2647
- return $tax_meta[$id];
2648
-
2649
- return null;
2650
- }
2651
-
2652
- /********** CRON FUNCTION **********/
2653
-
2654
- /**
2655
- * Creates a cron job if it doesn't already exists, and ensures it runs at the scheduled time.
2656
- * Should be called in a module's init() function.
2657
- *
2658
- * @since 0.1
2659
- * @uses get_module_key()
2660
- *
2661
- * @param string $function The name of the module function that should be run.
2662
- * @param string $recurrence How often the job should be run. Valid values are hourly, twicedaily, and daily.
2663
- */
2664
- function cron($function, $recurrence) {
2665
-
2666
- $mk = $this->get_module_key();
2667
-
2668
- $hook = "su-$mk-".str_replace('_', '-', $function);
2669
- $start = time();
2670
-
2671
- if (wp_next_scheduled($hook) === false) {
2672
- //This is a new cron job
2673
-
2674
- //Schedule the event
2675
- wp_schedule_event($start, $recurrence, $hook);
2676
-
2677
- //Make a record of it
2678
- $psdata = (array)get_option('seo_ultimate', array());
2679
- $psdata['cron'][$mk][$function] = array($hook, $start, $recurrence);
2680
- update_option('seo_ultimate', $psdata);
2681
-
2682
- //Run the event now
2683
- call_user_func(array($this, $function));
2684
- }
2685
-
2686
- add_action($hook, array(&$this, $function));
2687
- }
2688
-
2689
- /********** JLSUGGEST **********/
2690
-
2691
- /**
2692
- * Initializes JLSuggest.
2693
- * Must be called in the admin_page_init() function of the module that wants to use JLSuggest.
2694
- *
2695
- * @since 6.0
2696
- * @uses jlsuggest_xml_ns()
2697
- * @uses SEO_Ultimate::queue_js()
2698
- * @uses SEO_Ultimate::queue_css()
2699
- */
2700
- function jlsuggest_init() {
2701
- add_action('admin_xml_ns', array(&$this, 'jlsuggest_xml_ns'));
2702
- $this->plugin->queue_js ('includes', 'encoder');
2703
- $this->plugin->queue_js ('includes/jlsuggest', 'jlsuggest');
2704
- $this->plugin->queue_css('includes/jlsuggest', 'jlsuggest');
2705
- }
2706
-
2707
- /**
2708
- * Outputs the SEO Ultimate XMLNS used by JLSuggest.
2709
- *
2710
- * @since 6.0
2711
- */
2712
- function jlsuggest_xml_ns() {
2713
- echo ' xmlns:su="http://johnlamansky.com/xmlns/seo-ultimate" ';
2714
- }
2715
-
2716
- /**
2717
- * Explodes a JLSuggest database string into an array with the destination type and the destination ID.
2718
- *
2719
- * @since 6.0
2720
- *
2721
- * @param $valstr The database string, e.g. http://example.com or obj_posttype_post/1
2722
- * @return array
2723
- */
2724
- function jlsuggest_value_explode($valstr) {
2725
-
2726
- if (is_array($valstr)) {
2727
-
2728
- if (count($valstr) == 3)
2729
- return $valstr;
2730
-
2731
- } elseif (is_string($valstr)) {
2732
-
2733
- if (sustr::startswith($valstr, 'obj_')) {
2734
- $valstr = sustr::ltrim_str($valstr, 'obj_');
2735
-
2736
- $valarr = explode('/', $valstr);
2737
- if (count($valarr) == 2) {
2738
- $valarr_type = explode('_', $valarr[0], 2);
2739
- if (count($valarr_type) == 2)
2740
- return array($valarr_type[0], $valarr_type[1], $valarr[1]);
2741
- else
2742
- return array($valarr[0], null, $valarr[1]);
2743
- } else
2744
- return array($valstr, null, null);
2745
- } else {
2746
- return array('url', null, $valstr);
2747
- }
2748
- }
2749
-
2750
- return array('url', null, '');
2751
- }
2752
-
2753
- /**
2754
- * Returns the HTML code for a JLSuggest textbox
2755
- *
2756
- * @since 6.0
2757
- *
2758
- * @param string $name The value of the textbox's name/ID attributes
2759
- * @param string $value The current database string associated with this textbox
2760
- */
2761
- function get_jlsuggest_box($name, $value, $params='', $placeholder='') {
2762
-
2763
- list($to_genus, $to_type, $to_id) = $this->jlsuggest_value_explode($value);
2764
-
2765
- $text_dest = '';
2766
- $disabled = false;
2767
-
2768
- switch ($to_genus) {
2769
-
2770
- case 'posttype':
2771
- $selected_post = get_post($to_id);
2772
- if ($selected_post) {
2773
- $selected_post_type = get_post_type_object($selected_post->post_type);
2774
- $text_dest = $selected_post->post_title . '<span class="type">&nbsp;&mdash;&nbsp;'.$selected_post_type->labels->singular_name.'</span>';
2775
- } else {
2776
- $selected_post_type = get_post_type_object($to_type);
2777
- if ($selected_post_type)
2778
- $text_dest = sprintf(__('A Deleted %s', 'seo-ultimate'), $selected_post_type->labels->singular_name);
2779
- else
2780
- $text_dest = __('A Deleted Post', 'seo-ultimate');
2781
- $text_dest = '<span class="type">' . $text_dest . '</span>';
2782
- $disabled = true;
2783
- }
2784
- break;
2785
- case 'taxonomy':
2786
- if ($selected_taxonomy = get_taxonomy($to_type)) {
2787
- if ($selected_term = get_term($to_id, $selected_taxonomy->name)) {
2788
- $text_dest = $selected_term->name . '<span class="type">&nbsp;&mdash;&nbsp;'.$selected_taxonomy->labels->singular_name.'</span>';
2789
- } else {
2790
- $text_dest = sprintf(__('A Deleted %s', 'seo-ultimate'), $selected_taxonomy->labels->singular_name);
2791
- $text_dest = '<span class="type">' . $text_dest . '</span>';
2792
- $disabled = true;
2793
- }
2794
- } else {
2795
- $text_dest = __('A Deleted Term', 'seo-ultimate');
2796
- $text_dest = '<span class="type">' . $text_dest . '</span>';
2797
- $disabled = true;
2798
- }
2799
- break;
2800
- case 'home':
2801
- $text_dest = __('Blog Homepage', 'seo-ultimate');
2802
- break;
2803
- case 'author':
2804
- if (is_user_member_of_blog($to_id)) {
2805
- $selected_author = get_userdata($to_id);
2806
- $text_dest = $selected_author->user_login . '<span class="type">&nbsp;&mdash;&nbsp;'.__('Author', 'seo-ultimate').'</span>';
2807
- } else {
2808
- $text_dest = __('A Deleted User', 'seo-ultimate');
2809
- $text_dest = '<span class="type">' . $text_dest . '</span>';
2810
- $disabled = true;
2811
- }
2812
- break;
2813
- case 'internal-link-alias':
2814
-
2815
- $alias_dir = $this->get_setting('alias_dir', 'go', 'internal-link-aliases');
2816
- $aliases = $this->get_setting('aliases', array(), 'internal-link-aliases');
2817
-
2818
- if (isset($aliases[$to_id]['to'])) {
2819
- $h_alias_to = su_esc_html($aliases[$to_id]['to']);
2820
- $text_dest = "/$alias_dir/$h_alias_to/" . '<span class="type">&nbsp;&mdash;&nbsp;';
2821
-
2822
- if ($this->plugin->module_exists('internal-link-aliases')) {
2823
- $text_dest .= __('Link Mask', 'seo-ultimate');
2824
- } else {
2825
- $text_dest .= __('Link Mask (Disabled)', 'seo-ultimate');
2826
- $disabled = true;
2827
- }
2828
- $text_dest .= '</span>';
2829
- } else {
2830
- $text_dest = __('A Deleted Link Mask', 'seo-ultimate');
2831
- $text_dest = '<span class="type">' . $text_dest . '</span>';
2832
- $disabled = true;
2833
- }
2834
-
2835
- break;
2836
- }
2837
-
2838
- $is_url = (('url' == $to_genus) && !$text_dest);
2839
-
2840
- $to_genus_type = implode('_', array_filter(array($to_genus, $to_type)));
2841
- $obj = 'obj_' . implode('/', array_filter(array($to_genus_type, $to_id)));
2842
-
2843
- //URL textbox
2844
- //(hide if object is selected)
2845
- $html = "<input name='$name' id='$name' value='";
2846
- $html .= su_esc_editable_html($is_url ? $to_id : $obj);
2847
- $html .= "'";
2848
-
2849
- if ($params) {
2850
- $e_params = su_esc_attr($params);
2851
- $html .= " su:params='$e_params'";
2852
- }
2853
-
2854
- if ($placeholder) {
2855
- $e_placeholder = su_esc_attr($placeholder);
2856
- $html .= " placeholder='$e_placeholder'";
2857
- }
2858
-
2859
- $html .= " type='text' class='form-control input-sm textbox regular-text jlsuggest'";
2860
- $html .= ' title="' . __('Type a URL or start typing the name of an item on your site', 'seo-ultimate') . '"';
2861
- $html .= $is_url ? '' : ' style="display:none;" ';
2862
- $html .= ' />';
2863
-
2864
- //Object box
2865
- //(hide if URL is entered)
2866
- $disabled = $disabled ? ' jlsuggest-disabled' : '';
2867
- $html .= "<div class='jls_text_dest$disabled'";
2868
- $html .= $is_url ? ' style="display:none;" ' : '';
2869
- $html .= '>';
2870
- $html .= '<div class="jls_text_dest_text">';
2871
- $html .= $text_dest;
2872
- $html .= '</div>';
2873
- $html .= '<div><a href="#" onclick="javascript:return false;" class="jls_text_dest_close" title="'.__('Remove this location from this textbox', 'seo-ultimate').'">'.__('X', 'seo-ultimate').'</a></div>';
2874
- $html .= '</div>';
2875
-
2876
- return $html;
2877
- }
2878
-
2879
- /**
2880
- * Converts a JLSuggest database string into a URL.
2881
- *
2882
- * @since 6.0
2883
- *
2884
- * @param string $value The JLSuggest database string to convert.
2885
- * @param bool $get_src_if_media Whether to get the URL to the actual media item rather than the URL to its WP-powered singular page, if the item is an attachment.
2886
- * @return string The URL of the referenced destination
2887
- */
2888
- function jlsuggest_value_to_url($value, $get_src_if_media=false) {
2889
-
2890
- list($to_genus, $to_type, $to_id) = $this->jlsuggest_value_explode($value);
2891
-
2892
- switch ($to_genus) {
2893
- case 'url':
2894
- return $to_id; break;
2895
- case 'posttype':
2896
- $to_id = (int)$to_id;
2897
- switch (get_post_status($to_id)) {
2898
- case 'publish':
2899
- if ($get_src_if_media && 'attachment' == get_post_type($to_id))
2900
- return wp_get_attachment_url($to_id);
2901
-
2902
- return get_permalink($to_id);
2903
- case false: //Post doesn't exist
2904
- default: //Post exists but isn't published
2905
- return false;
2906
- }
2907
- break;
2908
- case 'taxonomy':
2909
- $to_id = (int)$to_id;
2910
- $term_link = get_term_link($to_id, $to_type);
2911
- if ($term_link && !is_wp_error($term_link)) return $term_link;
2912
- return false;
2913
- break;
2914
- case 'home':
2915
- return suwp::get_blog_home_url(); break;
2916
- case 'author':
2917
- $to_id = (int)$to_id;
2918
- if (is_user_member_of_blog($to_id))
2919
- return get_author_posts_url($to_id);
2920
- return false;
2921
- break;
2922
- case 'internal-link-alias':
2923
- if ($this->plugin->module_exists('internal-link-aliases')) {
2924
- $alias_dir = $this->get_setting('alias_dir', 'go', 'internal-link-aliases');
2925
- $aliases = $this->get_setting('aliases', array(),'internal-link-aliases');
2926
-
2927
- if (isset($aliases[$to_id]['to'])) {
2928
- $u_alias_to = urlencode($aliases[$to_id]['to']);
2929
- return get_bloginfo('url') . "/$alias_dir/$u_alias_to/";
2930
- }
2931
- }
2932
- return false;
2933
- break;
2934
- }
2935
-
2936
- return false;
2937
- }
2938
-
2939
-
2940
- /**
2941
- * @since 7.6
2942
- */
2943
- function should_show_sdf_theme_promo() {
2944
- return $this->is_sdf_theme_promo_applicable() && $this->get_setting('sdf_theme','', 'settings');
2945
- }
2946
-
2947
- /**
2948
- * @since 7.6
2949
- */
2950
- function is_sdf_theme_promo_applicable() {
2951
- //If the current user can install themes and if SDF isn't already uploaded...
2952
- if (current_user_can('install_themes') && (wp_get_theme('seodesign')->errors() === false)){
2953
- $theme = wp_get_theme(); // gets the current theme
2954
- return ('SEO Design Framework' == $theme->name || 'seodesign' == $theme->template || 'seodesign' == $theme->parent_theme) ? false : true;
2955
- }
2956
- else{
2957
- return true;
2958
- }
2959
- }
2960
-
2961
-
2962
- /**
2963
- * Display the RSS entries in a list.
2964
- *
2965
- * @since 7.6.2
2966
- *
2967
- * @param string|array|object $rss RSS url.
2968
- * @param array $args Widget arguments.
2969
- */
2970
- function promo_sdf_banners_rss_output( $rss, $args = array() ) {
2971
- if ( is_string( $rss ) ) {
2972
- $rss = fetch_feed($rss);
2973
- } elseif ( is_array($rss) && isset($rss['url']) ) {
2974
- $args = $rss;
2975
- $rss = fetch_feed($rss['url']);
2976
- } elseif ( !is_object($rss) ) {
2977
- return;
2978
- }
2979
-
2980
- if ( is_wp_error($rss) ) {
2981
- if ( is_admin() || current_user_can('manage_options') )
2982
- echo '<p>' . sprintf( __('<strong>RSS Error</strong>: %s'), $rss->get_error_message() ) . '</p>';
2983
- return;
2984
- }
2985
-
2986
- $default_args = array( 'show_author' => 0, 'show_date' => 0, 'show_summary' => 0 );
2987
- $args = wp_parse_args( $args, $default_args );
2988
- extract( $args, EXTR_SKIP );
2989
-
2990
- $items = (int) $items;
2991
- if ( $items < 1 || 20 < $items )
2992
- $items = 10;
2993
- $show_summary = (int) $show_summary;
2994
- $show_author = (int) $show_author;
2995
- $show_date = (int) $show_date;
2996
-
2997
- if ( !$rss->get_item_quantity() ) {
2998
- echo '<ul><li>' . __( 'An error has occurred, which probably means the feed is down. Try again later.' ) . '</li></ul>';
2999
- $rss->__destruct();
3000
- unset($rss);
3001
- return;
3002
- }
3003
-
3004
- foreach ( $rss->get_items(0, $items) as $item ) {
3005
- $link = $item->get_link();
3006
- while ( stristr($link, 'http') != $link )
3007
- $link = substr($link, 1);
3008
- $link = esc_url(strip_tags($link));
3009
- $title = esc_attr(strip_tags($item->get_title()));
3010
- if ( empty($title) )
3011
- $title = '';
3012
-
3013
- $desc = str_replace( array("\n", "\r"), ' ', esc_attr( strip_tags( @html_entity_decode( $item->get_description(), ENT_QUOTES, get_option('blog_charset') ) ) ) );
3014
- $excerpt = wp_html_excerpt( $desc, 120 );
3015
-
3016
- // Append ellipsis. Change existing [...] to [&hellip;].
3017
- if ( '[...]' == substr( $excerpt, -5 ) )
3018
- $excerpt = substr( $excerpt, 0, -5 ) . '[&hellip;]';
3019
- elseif ( '[&hellip;]' != substr( $excerpt, -10 ) && $desc != $excerpt )
3020
- $excerpt .= ' [&hellip;]';
3021
-
3022
- $excerpt = esc_html( $excerpt );
3023
-
3024
- if ( $show_summary ) {
3025
- $summary = "<p>$excerpt</p>";
3026
- } else {
3027
- $summary = '';
3028
- }
3029
-
3030
- $date = '';
3031
- if ( $show_date ) {
3032
- $date = $item->get_date( 'U' );
3033
-
3034
- if ( $date ) {
3035
- $date = ' <span class="rss-date">' . date_i18n( get_option( 'date_format' ), $date ) . '</span>';
3036
- }
3037
- }
3038
-
3039
- $author = '';
3040
- if ( $show_author ) {
3041
- $author = $item->get_author();
3042
- if ( is_object($author) ) {
3043
- $author = $author->get_name();
3044
- $author = ' <cite>' . esc_html( strip_tags( $author ) ) . '</cite>';
3045
- }
3046
- }
3047
-
3048
- if ( $link == '' ) {
3049
- echo "<h3>$title</h3>{$summary}";
3050
- } else {
3051
- echo "<h3>$title</h3>{$summary}<p><a class='btn btn-large btn-warning' href='$link' target='_blank' rel='nofollow'>Read More</a></p>";
3052
- }
3053
- }
3054
- $rss->__destruct();
3055
- unset($rss);
3056
- }
3057
-
3058
- /**
3059
- * @since 7.6.2
3060
- */
3061
- function promo_sdf_banners() {
3062
-
3063
- if ($this->should_show_sdf_theme_promo()) {
3064
- ?>
3065
- <div id="sds_promo_blog_post" class="hide">
3066
- <?php $this->promo_sdf_banners_rss_output( 'http://feeds.seodesignsolutions.com/SeoDesignSolutionsBlog', array('show_summary' => 1, 'show_date' => 0, 'items' => 1) ); ?>
3067
- </div>
3068
- <div id="sdf-promo-carousel"></div>
3069
- <p>Remove these ads?<br />
3070
- <a href="https://seoultimateplus.com/?ref=su-rmv-ad" target="_blank" title="Upgrade to SEO Ultimate+">Upgrade to SEO Ultimate+</a></p>
3071
- <?php
3072
- }
3073
- }
3074
- }
 
3075
  ?>
1
+ <?php
2
+ /**
3
+ * The pseudo-abstract class upon which all modules are based.
4
+ *
5
+ * @abstract
6
+ * @since 0.1
7
+ */
8
+ class SU_Module {
9
+
10
+ /********** VARIABLES **********/
11
+
12
+ /**
13
+ * @since 0.1
14
+ * @var string
15
+ */
16
+ var $module_key;
17
+
18
+ /**
19
+ * Stores the parent module (an SU_Module object) if this module has a parent.
20
+ *
21
+ * @since 1.5
22
+ * @var SU_Module
23
+ */
24
+ var $parent_module = null;
25
+
26
+ /**
27
+ * Stores any child modules as an array of SU_Module objects.
28
+ *
29
+ * @since 1.5
30
+ * @var array
31
+ */
32
+ var $modules = array();
33
+
34
+ /**
35
+ * Stores the module file's URL.
36
+ *
37
+ * @since 0.1
38
+ * @var string
39
+ */
40
+ var $module_url;
41
+
42
+ /**
43
+ * Stores the URL to the directory containing the module file. Has trailing slash.
44
+ *
45
+ * @since 1.5
46
+ * @var string
47
+ */
48
+ var $module_dir_url;
49
+
50
+ /**
51
+ * Stores the module file's URL relative to the plugin directory.
52
+ *
53
+ * @since 2.1
54
+ * @var string
55
+ */
56
+ var $module_rel_url;
57
+
58
+ /**
59
+ * Stores the URL to the directory containing the module file, relative to the plugin directory. Has trailing slash.
60
+ *
61
+ * @since 2.1
62
+ * @var string
63
+ */
64
+ var $module_dir_rel_url;
65
+
66
+ /**
67
+ * Stores the module's plugin page hook (the full hook with seo_page_ prefix).
68
+ * A reconstructed value of the get_plugin_page_hook() function, which is only available after admin init.
69
+ *
70
+ * @since 0.1
71
+ * @var string
72
+ */
73
+ var $plugin_page_hook;
74
+
75
+ /**
76
+ * Contains messages that are waiting to be displayed to the user.
77
+ *
78
+ * @since 0.1
79
+ * @var array
80
+ */
81
+ var $messages = array();
82
+
83
+ /**
84
+ * Stores the plugin object by reference.
85
+ *
86
+ * @since 1.5
87
+ */
88
+ var $plugin = null;
89
+
90
+
91
+ /********** CONSTRUCTOR FUNCTION **********/
92
+
93
+ /**
94
+ * PHP4 constructor that points to the likely-overloaded PHP5 constructor.
95
+ *
96
+ * @since 0.1
97
+ * @uses __construct()
98
+ */
99
+ /*function SU_Module() {
100
+ $this->__construct();
101
+ }*/
102
+
103
+
104
+ /********** PSEUDO-ABSTRACT FUNCTIONS **********/
105
+
106
+ /**
107
+ * PHP5 constructor.
108
+ *
109
+ * @since 0.1
110
+ */
111
+ function __construct() { }
112
+
113
+ /**
114
+ * The module's official title.
115
+ *
116
+ * @since 1.5
117
+ *
118
+ * @return string
119
+ */
120
+ static function get_module_title() { return ''; }
121
+
122
+ /**
123
+ * The title to be used by parent modules.
124
+ *
125
+ * @since 1.5
126
+ *
127
+ * @return string
128
+ */
129
+ function get_module_subtitle() { return isset($this) ? $this->get_module_title() : ''; }
130
+
131
+ /**
132
+ * The title of the admin page, which is displayed in the <title> and <h2> tags.
133
+ * Is the same as the menu title by default.
134
+ *
135
+ * @since 0.1
136
+ *
137
+ * @return string The title shown on this module's admin page.
138
+ */
139
+ function get_page_title() { return isset($this) ? $this->get_module_title() : ''; }
140
+
141
+ /**
142
+ * The title that appears on the administration navigation menu.
143
+ *
144
+ * @since 0.1
145
+ *
146
+ * @return string The title shown on the admin menu.
147
+ */
148
+
149
+ static function get_menu_title() { return isset($this) ? $this->get_module_title() : ''; }
150
+
151
+ /**
152
+ * Determines where this module's admin page should appear relative to those of other modules.
153
+ * If two modules have the same menu position index, they are sorted alphabetically.
154
+ *
155
+ * @since 0.1
156
+ *
157
+ * @return int The menu position index.
158
+ */
159
+ static function get_menu_pos() { return 10; }
160
+
161
+ /**
162
+ * Determines where this module's admin contents should appear on the parent page relative to those of other sibling modules.
163
+ * If two modules have the same order index, they are sorted alphabetically.
164
+ *
165
+ * @since 1.5
166
+ *
167
+ * @return int The child order index.
168
+ */
169
+ static function get_child_order() { return 999; }
170
+
171
+ /**
172
+ * The number that should be displayed in a bubble next to the module's menu title.
173
+ * A return value of zero means no bubble is shown.
174
+ *
175
+ * @since 0.1
176
+ *
177
+ * @return int The number that should be displayed.
178
+ */
179
+ function get_menu_count() {
180
+ $count = 0;
181
+ foreach ($this->modules as $key => $module) {
182
+ $count += $this->modules[$key]->get_menu_count();
183
+ }
184
+ return $count;
185
+ }
186
+
187
+ /**
188
+ * Whether or not the module will ever return a non-zero menu count.
189
+ *
190
+ * @since 1.5
191
+ *
192
+ * @return boolean
193
+ */
194
+ static function has_menu_count() { return false; }
195
+
196
+ /**
197
+ * A descriptive label of the menu count.
198
+ *
199
+ * @since 0.3
200
+ *
201
+ * @return string The label.
202
+ */
203
+ function get_menu_count_label() { return ''; }
204
+
205
+ /**
206
+ * Indicates under which top-level menu this module's admin page should go.
207
+ * Examples: seo (This plugin's SEO menu), options-general.php (The Settings menu)
208
+ *
209
+ * @since 0.1
210
+ *
211
+ * @return string The value to pass to WordPress's add_submenu_page() function.
212
+ */
213
+ function get_menu_parent(){ return 'seo'; }
214
+
215
+ /**
216
+ * Returns the hook of this module's menu parent.
217
+ * Examples: seo (This plugin's SEO menu), settings (The Settings menu), toplevel (The toplevel)
218
+ *
219
+ * @since 0.1
220
+ *
221
+ * @return string The hook of the module's menu parent.
222
+ */
223
+ function get_menu_parent_hook() { return $this->get_menu_parent(); }
224
+
225
+ /**
226
+ * @since 7.2.5
227
+ */
228
+ function belongs_in_admin($admin_scope = null) {
229
+
230
+ if ($admin_scope === null)
231
+ $admin_scope = suwp::get_admin_scope();
232
+
233
+ switch ($admin_scope) {
234
+ case 'blog':
235
+ return true;
236
+ break;
237
+ case 'network':
238
+ case 'user':
239
+ default:
240
+ return false;
241
+ break;
242
+ }
243
+ }
244
+
245
+ /**
246
+ * The status (enabled/silenced/hidden) of the module when the module is newly added to the plugin.
247
+ *
248
+ * @since 1.5
249
+ *
250
+ * @return int Either SU_MODULE_ENABLED, SU_MODULE_SILENCED, or SU_MODULE_HIDDEN.
251
+ */
252
+ function get_default_status() { return SU_MODULE_ENABLED; }
253
+
254
+ /**
255
+ * The module key of this module's parent. Defaults to false (no parent).
256
+ *
257
+ * @since 0.3
258
+ *
259
+ * @return string|bool
260
+ */
261
+ static function get_parent_module() { return false; }
262
+
263
+ /**
264
+ * Returns an array of admin page tabs; the label is the key and the callback is the value.
265
+ *
266
+ * @since 1.5
267
+ *
268
+ * @return array
269
+ */
270
+ function get_admin_page_tabs() { return array(); }
271
+
272
+ /**
273
+ * Whether or not the module can "exist on its own."
274
+ * Determines whether or not the module appears in the Module Manager.
275
+ *
276
+ * @since 1.5
277
+ *
278
+ * @return bool
279
+ */
280
+ static function is_independent_module() {
281
+ return true;
282
+ }
283
+
284
+ /**
285
+ * The array key of the plugin's settings array in which this module's settings are stored.
286
+ *
287
+ * @since 1.5
288
+ *
289
+ * @return string
290
+ */
291
+ function get_settings_key() {
292
+ if (isset($this)) {
293
+ if (strlen($parent = $this->get_parent_module()) && !$this->is_independent_module())
294
+ return $this->plugin->modules[$parent]->get_settings_key();
295
+ else
296
+ return $this->get_module_key();
297
+ } else {
298
+ if (strlen($parent = self::get_parent_module()) && !self::is_independent_module()) {
299
+ global $seo_ultimate;
300
+ return $seo_ultimate->modules[$parent]->get_settings_key();
301
+ } else {
302
+ if (strlen($parent = self::get_parent_module()) && !self::is_independent_module()) {
303
+ global $seo_ultimate;
304
+ return $seo_ultimate->get_module_key();
305
+ } else {
306
+ return false;
307
+ }
308
+ }
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Whether or not this module should be the default screen for the "SEO" menu.
314
+ *
315
+ * @since 1.5
316
+ * @return bool
317
+ */
318
+ function is_menu_default() { return false; }
319
+
320
+ /**
321
+ * Called after the module has been constructed and its variables have been filled.
322
+ *
323
+ * @since 3.9
324
+ */
325
+ function load() {}
326
+
327
+ /**
328
+ * Called at WordPress's init hook.
329
+ *
330
+ * @since 0.1
331
+ */
332
+ function init() {}
333
+
334
+ /**
335
+ * Called under 3 circumstances:
336
+ * 1. When the SEO Ultimate plugin is activated (not necessarily for the first time)
337
+ * 2. When a module is newly registered in the database, which can happen for two reasons:
338
+ * a. The plugin is activated *for the first time*
339
+ * b. The module has been newly added via a plugin upgrade
340
+ * 3. When the module is re-enabled in the Module Manager after being disabled.
341
+ *
342
+ * Note that this function will be called twice when the plugin is activated for the first time, since this will make #1 and #2 both true.
343
+ * If the plugin is deactivated and then reactivated, only #1 will be true.
344
+ *
345
+ * WARNING: Do not use "$this" in the activate() function. It will not work under condition #3. Check for isset($this) and if false, use self:: instead.
346
+ *
347
+ * @since 0.1
348
+ */
349
+ function activate() { }
350
+
351
+ /**
352
+ * Called under 2 circumstances:
353
+ * 1. When the SEO Ultimate plugin is deactivated or uninstalled.
354
+ * 2. When the module is disabled in the Module Manager.
355
+ *
356
+ * @since 7.2.8
357
+ */
358
+ function deactivate() { }
359
+
360
+ /**
361
+ * Called when SEO Ultimate has just been upgraded to a new version.
362
+ *
363
+ * @since 2.1
364
+ */
365
+ function upgrade() { }
366
+
367
+ /**
368
+ * Returns an array of default settings. The defaults will be saved in the database if the settings don't exist.
369
+ *
370
+ * @since 0.1
371
+ *
372
+ * @return array The default settings. (The setting name is the key, and the default value is the array value.)
373
+ */
374
+ function get_default_settings() { return array(); }
375
+
376
+ /**
377
+ * Is called at WordPress' admin_init hook when this module's admin page is showing.
378
+ *
379
+ * @since 6.0
380
+ */
381
+ function admin_page_init() { }
382
+
383
+ /**
384
+ * Is called at WordPress' admin_init hook when the post editor is loaded.
385
+ *
386
+ * @since 7.3
387
+ */
388
+ function editor_init() { }
389
+
390
+ /**
391
+ * The contents of the administration page.
392
+ *
393
+ * @since 0.1
394
+ */
395
+ function admin_page_contents() {
396
+ $this->children_admin_page_tabs_form();
397
+ }
398
+
399
+ /**
400
+ * Returns a list of possible admin table columns that should be registered in "Screen Options"
401
+ *
402
+ * @since 2.1
403
+ *
404
+ * @return array
405
+ */
406
+ function get_admin_table_columns() {
407
+ return array();
408
+ }
409
+
410
+ /**
411
+ * Called at WordPress's load-{page} hook for this module's admin page.
412
+ *
413
+ * @since 7.0
414
+ */
415
+ function load_hook() {
416
+ $this->add_help_tabs(get_current_screen());
417
+ }
418
+
419
+ /**
420
+ * @since 7.0
421
+ */
422
+ function add_help_tabs($screen) { }
423
+
424
+ /**
425
+ * Adds the module's post meta box field HTML to the array.
426
+ *
427
+ * @since 0.1
428
+ *
429
+ * @param array $fields The fields array.
430
+ * @return array The updated fields array.
431
+ */
432
+ function postmeta_fields($fields, $screen) { return $fields; }
433
+
434
+ /********** INITIALIZATION FUNCTIONALITY **********/
435
+
436
+ /**
437
+ * If settings are unset, apply the defaults if available.
438
+ *
439
+ * @since 0.5
440
+ * @uses get_default_settings()
441
+ * @uses get_setting()
442
+ * @uses update_setting()
443
+ */
444
+ function load_default_settings() {
445
+
446
+ $defaults = $this->get_default_settings();
447
+ foreach ($defaults as $setting => $default) {
448
+ if ($this->get_setting($setting, "{reset}") === "{reset}") {
449
+ $this->update_setting($setting, $default, null, null);
450
+ }
451
+ }
452
+ }
453
+
454
+
455
+ /********** MODULE FUNCTIONS **********/
456
+
457
+ /**
458
+ * Returns the array key of the module.
459
+ *
460
+ * @since 0.1
461
+ * @uses $module_key
462
+ *
463
+ * @return string The module key.
464
+ */
465
+ function get_module_key() {
466
+ if ($this->module_key)
467
+ return $this->module_key;
468
+ else
469
+ //This error will only be triggered if someone has seriously messed with the plugin architecture
470
+ die("An SEO Ultimate module did not initialize properly. Perhaps you're trying to load an SEO Ultimate module independent of the plugin?");
471
+ }
472
+
473
+ /**
474
+ * Returns the key of the parent module if there is one; if not, the key of the current module.
475
+ *
476
+ * @since 2.1
477
+ *
478
+ * @return string
479
+ */
480
+ function get_module_or_parent_key() {
481
+ return $this->has_enabled_parent() ? $this->get_parent_module() : $this->get_module_key();
482
+ }
483
+
484
+ /**
485
+ * Returns true only if this module has a parent AND that parent is enabled.
486
+ *
487
+ * @since 7.0
488
+ *
489
+ * @return bool
490
+ */
491
+ function has_enabled_parent() {
492
+ return (strlen($p = $this->get_parent_module()) && $this->plugin->module_exists($p));
493
+ }
494
+
495
+ /**
496
+ * Returns the absolute URL of the module's admin page.
497
+ *
498
+ * @since 0.7
499
+ *
500
+ * @param string|false $key The key of the module for which to generate the admin URL. Optional.
501
+ * @return string The absolute URL to the admin page.
502
+ */
503
+ function get_admin_url($key = false) {
504
+
505
+ $anchor = '';
506
+ if ($key === false) {
507
+ if (($key = $this->get_parent_module()) && $this->plugin->module_exists($key)) {
508
+
509
+ $tabs = $this->get_admin_page_tabs();
510
+ if (!is_array($tabs))
511
+ return false;
512
+
513
+ if (count($tabs)) {
514
+ $first_tab = reset($tabs);
515
+ $anchor = '#' . $first_tab['id'];
516
+ } else {
517
+ $anchor = '#' . $this->plugin->key_to_hook($this->get_module_key());
518
+ }
519
+ } else
520
+ $key = $this->get_module_key();
521
+ }
522
+
523
+ if (!$this->plugin->call_module_func($key, 'belongs_in_admin', $belongs_in_admin) || !$belongs_in_admin)
524
+ return false;
525
+
526
+ if (!$this->plugin->call_module_func($key, 'get_menu_title', $menu_title) || !$menu_title)
527
+ return false;
528
+
529
+ $basepage = 'admin.php';
530
+ if ($this->plugin->call_module_func($key, 'get_menu_parent', $custom_basepage) && sustr::endswith($custom_basepage, '.php'))
531
+ $basepage = $custom_basepage;
532
+
533
+ if (is_network_admin() && $this->belongs_in_admin('network'))
534
+ $admin_url = 'network_admin_url';
535
+ else
536
+ $admin_url = 'admin_url';
537
+
538
+ return $admin_url($basepage.'?page='.$this->plugin->key_to_hook($key).$anchor);
539
+ }
540
+
541
+ /**
542
+ * Returns an <a> link to the module's admin page, if the module is enabled.
543
+ *
544
+ * @since 1.0
545
+ * @uses get_admin_url()
546
+ *
547
+ * @param string|false $key The key of the module for which to generate the admin URL.
548
+ * @param string $label The text to go inside the <a> element.
549
+ * @return string The <a> element, if the module exists; otherwise, the label by itself.
550
+ */
551
+ function get_admin_link($key, $label) {
552
+
553
+ if ($key == false || $this->plugin->module_exists($key))
554
+ return sprintf('<a href="%s">%s</a>', $this->get_admin_url($key), $label);
555
+ else
556
+ return $label;
557
+ }
558
+
559
+ /**
560
+ * Returns a boolean indicating whether the user is currently viewing this module's admin page.
561
+ *
562
+ * @since 1.1.1
563
+ *
564
+ * @return bool Whether the user is currently viewing this module's admin page.
565
+ */
566
+ function is_module_admin_page() {
567
+ if (is_admin()) {
568
+ global $plugin_page;
569
+ if (strcmp($plugin_page, $this->plugin->key_to_hook($this->get_module_or_parent_key())) == 0) return true;
570
+ }
571
+
572
+ return false;
573
+ }
574
+
575
+ /**
576
+ * Returns the filename of the module's icon URL.
577
+ *
578
+ * @since 1.5
579
+ *
580
+ * @return string
581
+ */
582
+ function get_menu_icon_filename() {
583
+ $filenames = array(
584
+ $this->get_settings_key()
585
+ , $this->get_module_key()
586
+ , $this->get_parent_module()
587
+ );
588
+
589
+ foreach ($filenames as $filename) {
590
+ $image = $this->module_dir_url.$filename.'.png';
591
+ if (is_readable($image)) return $image;
592
+ }
593
+
594
+ return '';
595
+ }
596
+
597
+
598
+ /********** CHILD MODULE FUNCTIONS **********/
599
+
600
+ /**
601
+ * Finds child modules of this module and fills $this->modules accordingly.
602
+ *
603
+ * @since 1.5
604
+ */
605
+ function load_child_modules() {
606
+ foreach ($this->plugin->modules as $key => $x_module) {
607
+ if ($key != $this->get_module_key()) {
608
+ $module =& $this->plugin->modules[$key];
609
+ if ($module->get_parent_module() == $this->get_module_key()) {
610
+ $module->parent_module =& $this;
611
+ $this->modules[$key] =& $module;
612
+ }
613
+ }
614
+ }
615
+
616
+ if (count($this->modules) > 0)
617
+ @uasort($this->modules, array(&$this, 'module_sort_callback'));
618
+ }
619
+
620
+ /**
621
+ * Returns an array of this module's admin tabs plus those of its children.
622
+ *
623
+ * @since 1.5
624
+ * @return array
625
+ */
626
+ function get_children_admin_page_tabs() {
627
+ $tabs = $this->get_admin_page_tabs();
628
+ if (!is_array($tabs)) $tabs = array();
629
+
630
+ foreach ($this->modules as $key => $x_module) {
631
+ $module =& $this->modules[$key];
632
+
633
+ if ($module->belongs_in_admin()) {
634
+ $child_tabs = $module->get_admin_page_tabs();
635
+
636
+ if (is_array($child_tabs)) {
637
+
638
+ if (empty($child_tabs))
639
+ $child_tabs[] = array(
640
+ 'title' => $module->get_module_subtitle()
641
+ , 'id' => $this->plugin->key_to_hook($key)
642
+ , 'callback' => array(&$module, 'admin_page_contents')
643
+ );
644
+
645
+ foreach ($child_tabs as $child_tab) {
646
+ if (is_array($child_tab) && !is_array($child_tab['callback']))
647
+ $child_tab['callback'] = array(&$module, $child_tab['callback']);
648
+
649
+ $tabs[] = $child_tab;
650
+ }
651
+ }
652
+ }
653
+ }
654
+
655
+ return $tabs;
656
+ }
657
+
658
+ /**
659
+ * Outputs this module's admin tabs plus those of its children.
660
+ *
661
+ * @since 1.5
662
+ */
663
+ function children_admin_page_tabs() {
664
+ if (count($tabs = $this->get_children_admin_page_tabs()))
665
+ $this->admin_page_tabs($tabs);
666
+ }
667
+
668
+ /**
669
+ * Outputs a form containing this module's admin tabs plus those of its children.
670
+ *
671
+ * @since 1.5
672
+ */
673
+ function children_admin_page_tabs_form() {
674
+ if (count($tabs = $this->get_children_admin_page_tabs())) {
675
+ echo "\n\n<div class='row'>\n";
676
+ echo "\n\n<div class='col-sm-8 col-md-9'>\n";
677
+
678
+ $this->admin_form_start(false, false);
679
+ $this->admin_page_tabs($tabs);
680
+ $this->admin_form_end(null, false);
681
+
682
+ echo "\n\n</div>\n";
683
+ echo "\n\n<div class='col-sm-4 col-md-3'>\n";
684
+ $this->promo_sdf_banners();
685
+ echo "\n\n</div>\n";
686
+ echo "\n\n</div>\n";
687
+ }
688
+ }
689
+
690
+ /**
691
+ * Outputs the admin pages of this module's children, one after the other.
692
+ *
693
+ * @since 1.5
694
+ */
695
+ function children_admin_pages() {
696
+ foreach ($this->modules as $key => $x_module) {
697
+ echo "<div id='" . $this->plugin->key_to_hook($key) . "'>\n";
698
+ $this->modules[$key]->admin_subheader($this->modules[$key]->get_module_subtitle());
699
+ $this->modules[$key]->admin_page_contents();
700
+ echo "</div>\n";
701
+ }
702
+ }
703
+
704
+ /**
705
+ * Outputs a form containing the admin pages of this module's children, outputted one after the other.
706
+ *
707
+ * @since 1.5
708
+ */
709
+ function children_admin_pages_form() {
710
+ if (count($this->modules)) {
711
+ $this->admin_form_start(false, false);
712
+ $this->children_admin_pages();
713
+ $this->admin_form_end(null, false);
714
+ } else
715
+ $this->print_message('warning', sprintf(__('All the modules on this page have been disabled. You can re-enable them using the <a href="%s">Module Manager</a>.', 'seo-ultimate'), $this->get_admin_url('modules')));
716
+ }
717
+
718
+ /**
719
+ * Compares two modules to determine which of the two should be displayed first on the parent page.
720
+ * Sorts by child order first, and title second.
721
+ * Works as a uasort() callback.
722
+ *
723
+ * @since 1.5
724
+ * @uses SU_Module::get_child_order()
725
+ * @uses SU_Module::get_module_subtitle()
726
+ *
727
+ * @param SU_Module $a The first module to compare.
728
+ * @param SU_Module $b The second module to compare.
729
+ * @return int This will be -1 if $a comes first, or 1 if $b comes first.
730
+ */
731
+ function module_sort_callback($a, $b) {
732
+
733
+ if ($a->get_child_order() == $b->get_child_order()) {
734
+ return strcmp($a->get_module_subtitle(), $b->get_module_subtitle());
735
+ }
736
+
737
+ return ($a->get_child_order() < $b->get_child_order()) ? -1 : 1;
738
+ }
739
+
740
+ /********** SETTINGS FUNCTIONS **********/
741
+
742
+ /**
743
+ * Retrieves the given setting from a module's settings array.
744
+ *
745
+ * @since 0.1
746
+ * @uses get_settings_key()
747
+ *
748
+ * @param string $key The name of the setting to retrieve.
749
+ * @param mixed $default What should be returned if the setting does not exist. Optional.
750
+ * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
751
+ * @return mixed The value of the setting, or the $default variable.
752
+ */
753
+ function get_setting($key, $default=null, $module=null, $sneakpeak=false) {
754
+ if (!$module) $module = $this->get_settings_key();
755
+
756
+ $msdata = (array)get_option("seo_ultimate_module_$module", array());
757
+
758
+ if ($sneakpeak && $this->is_action('update'))
759
+ $setting = stripslashes(isset($_POST[$key]) ? $_POST[$key] : null);
760
+ elseif (isset($msdata[$key]))
761
+ $setting = $msdata[$key];
762
+ else
763
+ $setting = $default;
764
+
765
+ $setting = apply_filters("su_get_setting-$module", $setting, $key);
766
+ $setting = apply_filters("su_get_setting-$module-$key", $setting, $key);
767
+
768
+ return $setting;
769
+ }
770
+
771
+ /**
772
+ * Sets a value in the module's settings array.
773
+ *
774
+ * @since 0.1
775
+ * @uses get_settings_key()
776
+ *
777
+ * @param string $key The key of the setting to be changed.
778
+ * @param string $value The new value to assign to the setting.
779
+ * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
780
+ */
781
+ function update_setting($key, $value, $module=null, $array_key=null) {
782
+ if (!$module) $module = $this->get_settings_key();
783
+
784
+ $msdata = (array)get_option("seo_ultimate_module_$module", array());
785
+
786
+ $use_custom = apply_filters("su_custom_update_setting-$module-$key", false, $value, $key) ||
787
+ apply_filters("su_custom_update_setting-$module", false, $value, $key);
788
+
789
+ if (!$use_custom) {
790
+ if ($array_key)
791
+ $msdata[$key][$array_key] = $value;
792
+ else
793
+ $msdata[$key] = $value;
794
+ }
795
+
796
+ update_option("seo_ultimate_module_$module", $msdata);
797
+ }
798
+
799
+ /**
800
+ * Gets a setting's value, deletes the setting, and returns the value.
801
+ *
802
+ * @since 2.1
803
+ * @uses get_settings_key()
804
+ *
805
+ * @param string $key The name of the setting to retrieve/delete.
806
+ * @param mixed $default What should be returned if the setting does not exist. Optional.
807
+ * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
808
+ * @return mixed The value of the setting, or the $default variable.
809
+ */
810
+ function flush_setting($key, $default=null, $module=null) {
811
+ $setting = $this->get_setting($key, $default, $module); //We need to retrieve the setting before deleting it
812
+ $this->delete_setting($key, $module);
813
+ return $setting;
814
+ }
815
+
816
+ /**
817
+ * Deletes a module setting.
818
+ *
819
+ * @since 2.1
820
+ * @uses get_settings_key()
821
+ *
822
+ * @param string $key The name of the setting to delete.
823
+ * @param string|null $module The module to which the setting belongs. Defaults to the current module's settings key. Optional.
824
+ */
825
+ function delete_setting($key, $module=null, $array_key = null) {
826
+ if (!$module) $module = $this->get_settings_key();
827
+
828
+ $msdata = (array)get_option("seo_ultimate_module_$module", array());
829
+
830
+ if (isset($msdata[$key])) {
831
+ if ($array_key) {
832
+ if (isset($msdata[$key][$array_key]))
833
+ unset($msdata[$key][$array_key]);
834
+ } else {
835
+ unset($msdata[$key]);
836
+ }
837
+ }
838
+ }
839
+
840
+ /**
841
+ * Returns a default setting. Only use this function if a default is indeed provided!
842
+ *
843
+ * @since 1.3
844
+ * @uses get_default_settings()
845
+ *
846
+ * @param string $key The name of the setting whose default to retrieve.
847
+ * @return mixed The default value for the setting.
848
+ */
849
+ function get_default_setting($key) {
850
+ $defaults = $this->get_default_settings();
851
+ return $defaults[$key];
852
+ }
853
+
854
+
855
+ /********** ADMIN PAGE FUNCTIONS **********/
856
+
857
+ /**
858
+ * Displays the beginning, contents, and end of the module's administration page.
859
+ *
860
+ * @since 0.1
861
+ * @uses admin_page_start()
862
+ * @uses admin_page_contents()
863
+ * @uses admin_page_end()
864
+ */
865
+ function admin_page() {
866
+ if (!apply_filters('su_custom_admin_page-'.$this->get_module_key(), false)) {
867
+ $this->admin_page_start();
868
+ $this->admin_page_contents();
869
+ $this->admin_page_end();
870
+ }
871
+ }
872
+
873
+ /**
874
+ * Outputs the starting code for an administration page:
875
+ * wrapper, ID'd <div>, icon, and title
876
+ *
877
+ * @since 0.1
878
+ * @uses admin_footer() Hooked into WordPress's in_admin_footer action.
879
+ * @uses get_module_key()
880
+ * @uses get_page_title()
881
+ *
882
+ * @param string $icon The ID that should be applied to the icon element. The icon is loaded via CSS based on the ID. Optional.
883
+ */
884
+ function admin_page_start($icon = 'options-general') {
885
+
886
+ //Add our custom footer attribution
887
+ add_action('in_admin_footer', array(&$this, 'admin_footer'));
888
+
889
+ //Output the beginning of the admin screen
890
+ echo "<div class=\"wrap\">\n";
891
+
892
+ if (strcmp($pclass = strtolower(get_parent_class($this)), 'su_module') != 0)
893
+ $class = ' '.str_replace('_', '-', $pclass);
894
+ else
895
+ $class = '';
896
+
897
+ echo "<div id=\"su-".su_esc_attr($this->get_module_key())."\" class=\"sdf-admin$class\">\n";
898
+ screen_icon($icon);
899
+ echo "\n<h2>".$this->get_page_title()."</h2>\n";
900
+ }
901
+
902
+ /**
903
+ * Outputs an administration page subheader (an <h4> tag).
904
+ *
905
+ * @since 0.1
906
+ *
907
+ * @param string $title The text to output.
908
+ */
909
+ function admin_subheader($title, $id=false) {
910
+ if ($id) $id = ' id="' . su_esc_attr($id) . '"';
911
+ echo "<h4 class='su-subheader'$id>$title</h4>\n";
912
+ }
913
+
914
+ /**
915
+ * Outputs an administration form table subheader.
916
+ *
917
+ * @since 0.1
918
+ *
919
+ * @param string $title The text to output.
920
+ */
921
+ function admin_form_subheader($title) {
922
+ echo "<tr><th colspan='2'><strong>$title</strong></th></tr>\n";
923
+ }
924
+
925
+ /**
926
+ * Outputs the ending code for an administration page.
927
+ *
928
+ * @since 0.1
929
+ */
930
+ function admin_page_end() {
931
+ echo "\n</div>\n</div>\n";
932
+ }
933
+
934
+ /**
935
+ * Outputs a tab control and loads the current tab.
936
+ *
937
+ * @since 0.7
938
+ *
939
+ * @param array $tabs Array (id => __, title => __, callback => __)
940
+ * @param bool $table Whether or not the tab contents should be wrapped in a form table.
941
+ */
942
+ function admin_page_tabs($tabs=array(), $table=false) {
943
+ $this->plugin->tabs($tabs, $table, $this);
944
+ }
945
+
946
+ /**
947
+ * Adds the hook necessary to initialize the admin page tabs.
948
+ *
949
+ * @since 0.8
950
+ */
951
+ function admin_page_tabs_init() {
952
+ add_action('admin_enqueue_scripts', array(&$this, 'admin_page_tabs_js'));
953
+ }
954
+
955
+ /**
956
+ * Enqueues the JavaScript needed for the admin page tabs.
957
+ *
958
+ * @since 0.8
959
+ * @uses is_module_admin_page()
960
+ */
961
+ function admin_page_tabs_js() {
962
+ if ($this->is_module_admin_page())
963
+ wp_enqueue_script('jquery-ui-tabs');
964
+ }
965
+
966
+ /**
967
+ * Adds plugin/module information to the admin footer.
968
+ *
969
+ * @since 0.1
970
+ * @uses SU_PLUGIN_URI
971
+ * @uses SU_PLUGIN_NAME
972
+ * @uses SU_AUTHOR_URI
973
+ * @uses SU_AUTHOR
974
+ */
975
+ function admin_footer() {
976
+ printf(__('%1$s | %2$s %3$s by %4$s', 'seo-ultimate'),
977
+ $this->get_module_title(),
978
+ '<a href="'.SU_PLUGIN_URI.'" target="_blank" rel="nofollow">'.__(SU_PLUGIN_NAME, 'seo-ultimate').'</a>',
979
+ SU_VERSION,
980
+ '<a href="'.SU_AUTHOR_URI.'" target="_blank" rel="nofollow">'.__(SU_AUTHOR, 'seo-ultimate').'</a>'
981
+ );
982
+
983
+ echo "<br />";
984
+ }
985
+
986
+ /**
987
+ * Returns tabs for post/taxonomy meta editing tables.
988
+ *
989
+ * @since 2.9
990
+ * @uses get_postmeta_edit_tabs()
991
+ * @uses get_taxmeta_edit_tabs()
992
+ *
993
+ * @param array $fields The array of meta fields that the user can edit with the tables.
994
+ */
995
+ function get_meta_edit_tabs($fields) {
996
+ return array_merge(
997
+ $this->get_postmeta_edit_tabs($fields)
998
+ ,$this->get_taxmeta_edit_tabs($fields)
999
+ );
1000
+ }
1001
+
1002
+ /**
1003
+ * Returns tabs for post meta editing tables.
1004
+ *
1005
+ * @since 2.9
1006
+ *
1007
+ * @param array $fields The array of meta fields that the user can edit with the tables.
1008
+ */
1009
+ function get_postmeta_edit_tabs($fields) {
1010
+
1011
+ $types = get_post_types(array('public' => true), 'objects');
1012
+
1013
+ //Turn the types array into a tabs array
1014
+ $tabs = array();
1015
+ foreach ($types as $type)
1016
+ $tabs[$type->name] = array(
1017
+ 'title' => $type->labels->name
1018
+ , 'id' => 'su-' . $type->name
1019
+ , 'callback' => array('meta_edit_tab', 'post', 'su-' . $type->name, $type->name, $type->labels->singular_name, $fields)
1020
+ );
1021
+ return $tabs;
1022
+ }
1023
+
1024
+ /**
1025
+ * Returns tabs for taxonomy meta editing tables.
1026
+ *
1027
+ * @since 2.9
1028
+ *
1029
+ * @param array $fields The array of meta fields that the user can edit with the tables.
1030
+ */
1031
+ function get_taxmeta_edit_tabs($fields) {
1032
+ $types = suwp::get_taxonomies();
1033
+
1034
+ //Turn the types array into a tabs array
1035
+ $tabs = array();
1036
+ foreach ($types as $name => $type) {
1037
+ if ($type->labels->name) {
1038
+ $tabs[] = array(
1039
+ 'title' => $type->labels->name
1040
+ , 'id' => 'su-' . $name
1041
+ , 'callback' => array('meta_edit_tab', 'term', 'su-' . $name, $name, $type->labels->singular_name, $fields)
1042
+ );
1043
+ }
1044
+ }
1045
+ return $tabs;
1046
+ }
1047
+
1048
+ /**
1049
+ * Outputs the contents of a meta editing tab.
1050
+ *
1051
+ * @since 2.9
1052
+ */
1053
+ function meta_edit_tab($genus, $tab, $type, $type_label, $fields) {
1054
+ if (!$this->meta_edit_table($genus, $tab, $type, $type_label, $fields))
1055
+ $this->print_message('info', __('Your site currently doesn&#8217;t have any public items of this type.', 'seo-ultimate'));
1056
+ }
1057
+
1058
+ /**
1059
+ * Outputs the contents of a meta editing table.
1060
+ *
1061
+ * @since 2.9
1062
+ *
1063
+ * @param string $genus The type of object being handled (either 'post' or 'term')
1064
+ * @param string $tab The ID of the current tab; used to generate a URL hash (e.g. #$tab)
1065
+ * @param string $type The type of post/taxonomy type being edited (examples: post, page, attachment, category, post_tag)
1066
+ * @param string $type_label The singular label for the post/taxonomy type (examples: Post, Page, Attachment, Category, Post Tag)
1067
+ * @param array $fields The array of meta fields that the user can edit with the tables. The data for each meta field are stored in an array with these elements: "type" (can be textbox, textarea, or checkbox), "name" (the meta field, e.g. title or description), "term_settings_key" (the key of the setting for cases when term meta data are stored in the settings array), and "label" (the internationalized label of the field, e.g. "Meta Description" or "Title Tag")
1068
+ */
1069
+ function meta_edit_table($genus, $tab, $type, $type_label, $fields) {
1070
+
1071
+ //Pseudo-constant
1072
+ $per_page = 100;
1073
+
1074
+ //Sanitize parameters
1075
+ if (!is_array($fields) || !count($fields)) return false;
1076
+ if (!isset($fields[0]) || !is_array($fields[0])) $fields = array($fields);
1077
+
1078
+ //Get search query
1079
+ $type_s = $type . '_s';
1080
+ $search = isset($_REQUEST[$type_s]) ? $_REQUEST[$type_s] : '';
1081
+
1082
+ //Save meta if applicable
1083
+ if ($is_update = ($this->is_action('update') && !strlen(trim($search)))) {
1084
+ foreach ($_POST as $key => $value) {
1085
+ $value = stripslashes($value);
1086
+ if (sustr::startswith($key, $genus.'_'))
1087
+ foreach ($fields as $field)
1088
+ if (preg_match("/{$genus}_([0-9]+)_{$field['name']}/", $key, $matches)) {
1089
+ $id = (int)$matches[1];
1090
+ switch ($genus) {
1091
+ case 'post': update_post_meta($id, "_su_{$field['name']}", $value); break;
1092
+ case 'term': $this->update_setting($field['term_settings_key'], $value, null, $id); break;
1093
+ }
1094
+ continue 2; //Go to next $_POST item
1095
+ }
1096
+ }
1097
+ }
1098
+
1099
+ $pagenum = isset( $_GET[$type . '_paged'] ) ? absint( $_GET[$type . '_paged'] ) : 0;
1100
+ if ( empty($pagenum) ) $pagenum = 1;
1101
+
1102
+ //Load up the objects based on the genus
1103
+ switch ($genus) {
1104
+ case 'post':
1105
+
1106
+ //Get the posts
1107
+ wp(array(
1108
+ 'post_type' => $type
1109
+ , 'posts_per_page' => $per_page
1110
+ , 'post_status' => 'any'
1111
+ , 'paged' => $pagenum
1112
+ , 'order' => 'ASC'
1113
+ , 'orderby' => 'title'
1114
+ , 's' => $search
1115
+ ));
1116
+ global $wp_query;
1117
+ $objects = &$wp_query->posts;
1118
+
1119
+ $num_pages = $wp_query->max_num_pages;
1120
+ $total_objects = $wp_query->found_posts;
1121
+
1122
+ break;
1123
+
1124
+ case 'term':
1125
+ $objects = get_terms($type, array('search' => $search));
1126
+ $total_objects = count($objects);
1127
+ $num_pages = ceil($total_objects / $per_page);
1128
+ $objects = array_slice($objects, $per_page * ($pagenum-1), $per_page);
1129
+ break;
1130
+ default:
1131
+ return false;
1132
+ break;
1133
+ }
1134
+
1135
+ if ($total_objects < 1) return false;
1136
+
1137
+ echo "\n<div class='su-meta-edit-table'>\n";
1138
+
1139
+ $page_links = paginate_links( array(
1140
+ 'base' => html_entity_decode( esc_url( add_query_arg( $type . '_paged', '%#%' ) ) ) . '#' . $tab
1141
+ , 'format' => ''
1142
+ , 'prev_text' => __('&laquo;')
1143
+ , 'next_text' => __('&raquo;')
1144
+ , 'total' => $num_pages
1145
+ , 'current' => $pagenum
1146
+ , 'add_args' => false
1147
+ ));
1148
+
1149
+ if ( $page_links ) {
1150
+ $page_links_text = '<div class="tablenav"><div class="tablenav-pages">';
1151
+ $page_links_text .= sprintf( '<span class="displaying-num">' . __( 'Displaying %s&#8211;%s of %s' ) . '</span>%s',
1152
+ number_format_i18n( ( $pagenum - 1 ) * $per_page + 1 ),
1153
+ number_format_i18n( min( $pagenum * $per_page, $total_objects ) ),
1154
+ number_format_i18n( $total_objects ),
1155
+ $page_links
1156
+ );
1157
+ $page_links_text .= "</div></div>\n";
1158
+
1159
+ echo $page_links_text;
1160
+ } else $page_links_text = '';
1161
+
1162
+ //Get object identification headers
1163
+ $headers = array(
1164
+ 'actions' => __('Actions', 'seo-ultimate')
1165
+ , 'id' => __('ID', 'seo-ultimate')
1166
+ , 'name' => $type_label
1167
+ );
1168
+
1169
+ //Get meta field headers
1170
+ foreach ($fields as $field) {
1171
+ $headers[$field['name']] = $field['label'];
1172
+ }
1173
+
1174
+ //Output all headers
1175
+ $this->admin_wftable_start($headers);
1176
+
1177
+ //Output rows
1178
+ foreach ($objects as $object) {
1179
+
1180
+ switch ($genus) {
1181
+ case 'post':
1182
+ $id = intval($object->ID);
1183
+ $name = $object->post_title;
1184
+ $view_url = get_permalink($id);
1185
+ $edit_url = get_edit_post_link($id);
1186
+
1187
+ $status_obj = get_post_status_object($object->post_status);
1188
+ switch ($object->post_status) {
1189
+ case 'publish': $status = ''; break;
1190
+ case 'inherit': $status = ''; break;
1191
+ case 'auto-draft': continue; break;
1192
+ default: $status = $status_obj->label; break;
1193
+ }
1194
+
1195
+ if ($status)
1196
+ $name .= "<span class='su-meta-table-post-status'> &mdash; $status</span>";
1197
+
1198
+ break;
1199
+ case 'term':
1200
+ if (!isset($object->term_taxonomy_id)) {
1201
+ $id = intval($object->term_id);
1202
+ $view_url = get_term_link($id, $type);
1203
+ }
1204
+ else{
1205
+ $id = intval($object->term_id);
1206
+ $view_url = get_term_link(intval($object->term_id), $type);
1207
+ }
1208
+ $name = $object->name;
1209
+
1210
+ $edit_url = suwp::get_edit_term_link($id, $type);
1211
+ break;
1212
+ default: return false; break;
1213
+ }
1214
+
1215
+ $view_url = su_esc_attr($view_url);
1216
+ $edit_url = su_esc_attr($edit_url);
1217
+
1218
+ $actions = array(sprintf('<a href="%s">%s</a>', $view_url, __('View', 'seo-ultimate')));
1219
+ if ($edit_url)
1220
+ $actions[] = sprintf('<a href="%s">%s</a>', $edit_url, __('Edit', 'seo-ultimate'));
1221
+ $actions = implode(' | ', $actions);
1222
+
1223
+ $cells = compact('actions', 'id', 'name');
1224
+
1225
+ //Get meta field cells
1226
+ foreach ($fields as $field) {
1227
+ $inputid = "{$genus}_{$id}_{$field['name']}";
1228
+
1229
+ switch ($genus) {
1230
+ case 'post':
1231
+ $value = $this->get_postmeta($field['name'], $id);
1232
+ break;
1233
+ case 'term':
1234
+ $value = $this->get_setting($field['term_settings_key'], array());
1235
+ $value = isset($value[$id]) ? $value[$id] : null;
1236
+ break;
1237
+ }
1238
+
1239
+ if ($is_update && $field['type'] == 'checkbox' && $value == '1' && !isset($_POST[$inputid]))
1240
+ switch ($genus) {
1241
+ case 'post': delete_post_meta($id, "_su_{$field['name']}"); $value = 0; break;
1242
+ case 'term': $this->update_setting($field['term_settings_key'], false, null, $id); break;
1243
+ }
1244
+
1245
+ $cells[$field['name']] = $this->get_input_element(
1246
+ $field['type'] //Type
1247
+ , $inputid
1248
+ , $value
1249
+ , isset($field['options']) ? $field['options'] : false
1250
+ );
1251
+ }
1252
+
1253
+ //Output all cells
1254
+ $this->table_row($cells, $id, $type);
1255
+ }
1256
+
1257
+ //End table
1258
+ $this->admin_wftable_end();
1259
+
1260
+ echo $page_links_text;
1261
+
1262
+ echo "</div>\n";
1263
+
1264
+ return true;
1265
+ }
1266
+
1267
+ /**
1268
+ * Returns the HTML for a given type of input element, without any surrounding <td> elements etc.
1269
+ *
1270
+ * @since 2.9
1271
+ *
1272
+ * @param string $type The type of input element (can be textbox, textarea, or checkbox)
1273
+ * @param string $inputid The name/ID of the input element
1274
+ * @param string $value The current value of the field
1275
+ * @return string
1276
+ */
1277
+ function get_input_element($type, $name, $value=null, $extra=false, $inputid=true) {
1278
+ if ($value === null) $value = $this->get_setting($name);
1279
+
1280
+ if ($inputid === true) $inputid = $name;
1281
+ if (strlen($inputid)) $inputid = " id='".su_esc_attr($inputid)."'";
1282
+
1283
+ //Get HTML element
1284
+ switch ($type) {
1285
+ case 'textbox':
1286
+ $value = su_esc_editable_html($value);
1287
+ $placeholder = $extra ? " placeholder='" . su_esc_attr($extra) . "'" : '';
1288
+ return "<input name='$name'$inputid value='$value'$placeholder type='text' class='form-control input-sm textbox regular-text' />";
1289
+ break;
1290
+ case 'textarea':
1291
+ $value = su_esc_editable_html($value);
1292
+ return "<textarea name='$name'$inputid type='text' rows='3' cols='50' class='textarea form-control regular-text'>$value</textarea>";
1293
+ break;
1294
+ case 'checkbox':
1295
+ $checked = $value ? " checked='checked'" : '';
1296
+ $html = "<input name='$name'$inputid value='1' type='checkbox' class='checkbox'$checked />";
1297
+ if (is_string($extra)) {
1298
+ $extra = su_esc_html($extra);
1299
+ $html = "<label>$html&nbsp;$extra</label>";
1300
+ }
1301
+ return $html;
1302
+ break;
1303
+ case 'dropdown':
1304
+ $html = "<select name='$name'$inputid onchange='javascript:su_toggle_select_children(this)' class='dropdown'>";
1305
+ if (is_array($extra)) $html .= suhtml::option_tags($extra, $value); else $html .= $extra;
1306
+ $html .= "</select>";
1307
+ return $html;
1308
+ break;
1309
+ case 'hidden':
1310
+ return "<input name='$name'$inputid value='$value' type='hidden' />";
1311
+ break;
1312
+ case 'jlsuggest':
1313
+ $params = isset($extra['params']) ? $extra['params'] : '';
1314
+ $placeholder = isset($extra['placeholder']) ? $extra['placeholder'] : '';
1315
+
1316
+ return $this->get_jlsuggest_box($name, $value, $params, $placeholder);
1317
+ break;
1318
+ }
1319
+
1320
+ return '';
1321
+ }
1322
+
1323
+ /**
1324
+ * Creates an admin form subsection.
1325
+ *
1326
+ * @since 3.8
1327
+ * @uses get_setting()
1328
+ * @see get_input_element()
1329
+ *
1330
+ * @param string $field
1331
+ * @param string|null $current_value
1332
+ * @param string $trigger_value
1333
+ * @param string $html
1334
+ * @return string
1335
+ */
1336
+ function get_admin_form_subsection($field, $current_value, $trigger_value, $html) {
1337
+ if ($current_value === null) $current_value = $this->get_setting($field);
1338
+ $hidden = ($current_value == $trigger_value) ? '' : ' hidden';
1339
+
1340
+ $field = su_esc_attr($field);
1341
+ $trigger_value = su_esc_attr($trigger_value);
1342
+ $html = "<div class='su_{$field}_{$trigger_value}_subsection$hidden'>$html</div>";
1343
+ return $html;
1344
+ }
1345
+
1346
+ /**
1347
+ * Creates multiple admin form subsections.
1348
+ *
1349
+ * @since 3.8
1350
+ * @uses get_admin_form_subsection()
1351
+ * @see get_input_element()
1352
+ *
1353
+ * @param string $field
1354
+ * @param array $subsections Array of ($field => $trigger_value)
1355
+ * @return string
1356
+ */
1357
+ function get_admin_form_subsections($field, $current_value, $subsections) {
1358
+ $allhtml = '';
1359
+ if (!in_array($current_value, $subsection_keys = array_keys($subsections))) $current_value = $subsection_keys[0];
1360
+ foreach ($subsections as $trigger_value => $html)
1361
+ $allhtml .= $this->get_admin_form_subsection($field, $current_value, $trigger_value, $html);
1362
+ return $allhtml;
1363
+ }
1364
+
1365
+
1366
+ /********** ADMIN FORM FUNCTIONS **********/
1367
+
1368
+ /**
1369
+ * Begins an administration form.
1370
+ * Outputs a subheader if provided, queues a success message upon settings update, outputs queued messages,
1371
+ * opens a form tag, outputs a nonce field and other WordPress fields, and begins a form table.
1372
+ *
1373
+ * @since 0.1
1374
+ * @uses SEO_Ultimate::key_to_hook()
1375
+ * @uses get_module_key()
1376
+ * @uses admin_subheader()
1377
+ * @uses is_action()
1378
+ * @uses print_message()
1379
+ * @uses get_parent_module()
1380
+ *
1381
+ * @param mixed $header The text of the subheader that should go right before the form. Optional.
1382
+ * @param boolean $table Whether or not to start a form table.
1383
+ */
1384
+ function admin_form_start($header = false, $table = true, $form = true) {
1385
+
1386
+ if ($header) $this->admin_subheader($header);
1387
+
1388
+ if ($form) {
1389
+ $hook = $this->plugin->key_to_hook($this->get_module_or_parent_key());
1390
+ if ($this->is_action('update')) $this->print_message('success', __('Settings updated.', 'seo-ultimate'));
1391
+ echo "<form id='su-admin-form' class='form-horizontal' method='post' action='?page=$hook'>\n";
1392
+ settings_fields($hook);
1393
+ }
1394
+
1395
+ echo "\n";
1396
+ //if ($table) echo "<table class='form-table'>\n";
1397
+ }
1398
+
1399
+ /**
1400
+ * Ends an administration form.
1401
+ * Closes the table tag, outputs a "Save Changes" button, and closes the form tag.
1402
+ *
1403
+ * @since 0.1
1404
+ * @uses get_parent_module()
1405
+ *
1406
+ * @param string|false $button The label of the submit button.
1407
+ * @param boolean $table Whether or not a form table should be ended.
1408
+ */
1409
+ function admin_form_end($button = null, $table = true) {
1410
+
1411
+ if ($button === null) $button = __('Save Changes'); //This string is used in normal WP, so we don't need a textdomain
1412
+ //if ($table) echo "</table>\n";
1413
+
1414
+ if ($button !== false) {
1415
+ ?>
1416
+ <p class="submit">
1417
+ <input type="submit" class="button-primary" value="<?php echo $button ?>" />
1418
+ </p>
1419
+ </form>
1420
+ <?php
1421
+ }
1422
+ }
1423
+
1424
+ /**
1425
+ * Begins an admin form table.
1426
+ *
1427
+ * @since 1.5
1428
+ */
1429
+ function admin_form_table_start() {
1430
+ //echo "<table class='form-table'>\n";
1431
+ }
1432
+
1433
+ /**
1434
+ * Ends an admin form table
1435
+ *
1436
+ * @since 1.5
1437
+ */
1438
+ function admin_form_table_end() {
1439
+ //echo "</table>\n";
1440
+ }
1441
+
1442
+ /**
1443
+ * @since 5.8
1444
+ */
1445
+ function child_admin_form_start($table=true) {
1446
+ if ($this->get_parent_module() && $this->plugin->module_exists($this->get_parent_module())) {
1447
+ if ($table) $this->admin_form_table_start();
1448
+ } else {
1449
+ $this->admin_form_start(false, $table);
1450
+ }
1451
+ }
1452
+
1453
+ /**
1454
+ * @since 5.8
1455
+ */
1456
+ function child_admin_form_end($table=true) {
1457
+ if ($this->get_parent_module() && $this->plugin->module_exists($this->get_parent_module())) {
1458
+ if ($table) $this->admin_form_table_end();
1459
+ } else {
1460
+ $this->admin_form_end(null, $table);
1461
+ }
1462
+ }
1463
+
1464
+ /**
1465
+ * Begins a "widefat" WordPress table.
1466
+ *
1467
+ * @since 1.8
1468
+ *
1469
+ * @param $headers Array of (CSS class => Internationalized column title)
1470
+ */
1471
+ function admin_wftable_start($headers = false) {
1472
+ echo "\n<table class='table table-bordered'>\n";
1473
+ if ($headers)
1474
+ $this->table_column_headers($headers);
1475
+ else {
1476
+ echo "\t<thead><tr>\n";
1477
+ print_column_headers($this->plugin_page_hook);
1478
+ echo "\t</tr></thead>\n";
1479
+ echo "\t<tfoot><tr>\n";
1480
+ print_column_headers($this->plugin_page_hook);
1481
+ echo "\t</tr></tfoot>\n";
1482
+ }
1483
+ echo "\t<tbody>\n";
1484
+ }
1485
+
1486
+ /**
1487
+ * Outputs a <tr> of <th scope="col"></th> tags based on an array of column headers.
1488
+ *
1489
+ * @since 2.1
1490
+ *
1491
+ * @param $headers Array of (CSS class => Internationalized column title)
1492
+ */
1493
+ function table_column_headers($headers) {
1494
+ echo "\t<thead><tr>\n";
1495
+ $mk = $this->get_module_key();
1496
+ foreach ($headers as $class => $header) {
1497
+ $class = is_numeric($class) ? '' : " class='su-$mk-$class su-$class'";
1498
+ echo "\t\t<th scope='col'$class>$header</th>\n";
1499
+ }
1500
+ echo "\t</tr></thead>\n";
1501
+ }
1502
+
1503
+ /**
1504
+ * Outputs <td> tags based on an array of cell data.
1505
+ *
1506
+ * @since 2.1
1507
+ *
1508
+ * @param $headers Array of (CSS class => Cell data)
1509
+ */
1510
+ function table_cells($cells) {
1511
+
1512
+ if (count($this->get_admin_table_columns())) {
1513
+ $columns = get_column_headers($this->plugin_page_hook);
1514
+ $hidden = get_hidden_columns($this->plugin_page_hook);
1515
+ foreach ( $columns as $column_name => $column_display_name ) {
1516
+ $class = "class=\"$column_name column-$column_name\"";
1517
+ $style = in_array($column_name, $hidden) ? ' style="display:none;"' : '';
1518
+ echo "\t\t<td $class$style>".$cells[$column_name]."</td>\n";
1519
+ }
1520
+ } elseif (is_array($cells) && count($cells)) {
1521
+ foreach ($cells as $class => $content) {
1522
+ $class = is_numeric($class) ? '' : " class='su-$class'";
1523
+ echo "\t\t<td$class>$content</td>\n";
1524
+ }
1525
+ }
1526
+ }
1527
+
1528
+ /**
1529
+ * Outputs a <tr> tag with <td> children.
1530
+ *
1531
+ * @since 2.9
1532
+ */
1533
+ function table_row($cells, $id, $class) {
1534
+ $mk = $this->get_module_key();
1535
+ echo "\t<tr id='su-$mk-$id' class='su-$mk-$class'>\n";
1536
+ $this->table_cells($cells);
1537
+ echo "\t</tr>\n";
1538
+ }
1539
+
1540
+ /**
1541
+ * Ends a "widefat" WordPress table.
1542
+ *
1543
+ * @since 1.8
1544
+ */
1545
+ function admin_wftable_end() {
1546
+ echo "\t</tbody>\n</table>\n";
1547
+ }
1548
+
1549
+ /**
1550
+ * Outputs the HTML that begins an admin form group.
1551
+ *
1552
+ * @since 1.5
1553
+ *
1554
+ * @param string $title The title of the group.
1555
+ * @param bool $newtable Whether to open a new <table> element.
1556
+ */
1557
+ function admin_form_group_start($title, $newtable=true) {
1558
+ echo "<div class='form-group'>\n<label class='col-sm-4 col-md-4 control-label'>$title</label><div class='col-sm-4 col-md-4'>\n";
1559
+ }
1560
+
1561
+ /**
1562
+ * Outputs the HTML that ends an admin form group.
1563
+ *
1564
+ * @since 1.5
1565
+ *
1566
+ * @param bool $newtable Whether to close a <table> element.
1567
+ */
1568
+ function admin_form_group_end($newtable=true) {
1569
+ echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
1570
+ }
1571
+
1572
+ function admin_form_indent_start() {
1573
+ echo "<div class='form-group'><div class='col-md-12'>";
1574
+ }
1575
+
1576
+ function admin_form_indent_end() {
1577
+ echo "</div></div>";
1578
+ }
1579
+
1580
+ /**
1581
+ * Outputs a text block into an admin form.
1582
+ *
1583
+ * @since 1.5
1584
+ *
1585
+ * @param string $text
1586
+ */
1587
+ function textblock($text) {
1588
+ echo "<div class='form-group su-admin-form-textblock'>\n<div class='col-md-12'>\n";
1589
+ echo $text;
1590
+ echo "\n</div>\n</div>\n";
1591
+ }
1592
+
1593
+ /**
1594
+ * Outputs a group of checkboxes into an admin form, and saves the values into the database after form submission.
1595
+ *
1596
+ * @since 0.1
1597
+ * @uses is_action()
1598
+ * @uses update_setting()
1599
+ * @uses get_module_key()
1600
+ * @uses get_setting()
1601
+ *
1602
+ * @param array $checkboxes An array of checkboxes. (Field/setting IDs are the keys, and descriptions are the values.)
1603
+ * @param mixed $grouptext The text to display in a table cell to the left of the one containing the checkboxes. Optional.
1604
+ */
1605
+ function checkboxes($checkboxes, $grouptext=false, $args=array()) {
1606
+
1607
+ extract(wp_parse_args($args, array(
1608
+ 'output_tr' => true
1609
+ )));
1610
+
1611
+ //Save checkbox settings after form submission
1612
+ if ($this->is_action('update')) {
1613
+ foreach ($checkboxes as $name => $desc) {
1614
+ $new_value = isset($_POST[$name]) ? ($_POST[$name] == '1') : false;
1615
+
1616
+ if (is_array($desc)) {
1617
+ $disabled = isset($desc['disabled']) ? $desc['disabled'] : false;
1618
+ $desc = isset($desc['description']) ? $desc['description'] : '';
1619
+ } else {
1620
+ $disabled = false;
1621
+ }
1622
+
1623
+ if (!$disabled)
1624
+ $this->update_setting($name, $new_value);
1625
+
1626
+ if (strpos($desc, '%d') !== false) {
1627
+ $name .= '_value';
1628
+ $this->update_setting($name, sustr::to_int($_POST[$name]));
1629
+ }
1630
+ }
1631
+ }
1632
+
1633
+ if ($grouptext)
1634
+ $this->admin_form_group_start($grouptext, false);
1635
+ elseif ($output_tr)
1636
+ echo "<div class='form-group su-admin-form-checkbox'>\n<div class='col-md-12'>\n";
1637
+
1638
+ if (is_array($checkboxes)) {
1639
+ foreach ($checkboxes as $name => $desc) {
1640
+
1641
+ if (is_array($desc)) {
1642
+ $indent = isset($desc['indent']) ? $desc['indent'] : false;
1643
+ $disabled = isset($desc['disabled']) ? $desc['disabled'] : false;
1644
+ $checked = isset($desc['checked']) ? $desc['checked'] : null;
1645
+ $desc = $desc['description'];
1646
+ } else {
1647
+ $indent = false;
1648
+ $disabled = false;
1649
+ $checked = null;
1650
+ }
1651
+
1652
+ register_setting($this->get_module_key(), $name, array('sustr', 'to_int'));
1653
+ $name = su_esc_attr($name);
1654
+
1655
+ if (strpos($desc, '%d') === false) {
1656
+ $onclick = '';
1657
+ } else {
1658
+ $int_var_name = $name.'_value';
1659
+ $int_var_value = sustr::to_int($this->get_setting($int_var_name));
1660
+ if ($this->get_setting($name) === true) $sfdisabled = ''; else $sfdisabled = "readonly='readonly' ";
1661
+ $desc = str_replace('%d', "</label><input name='$int_var_name' id='$int_var_name' class='form-control input-sm nowidth-input' type='text' value='$int_var_value' size='2' maxlength='3' $sfdisabled/><label for='$name'>", $desc);
1662
+ $desc = str_replace("<label for='$name'></label>", '', $desc);
1663
+ $onclick = " onclick=\"javascript:document.getElementById('$int_var_name').readOnly=!this.checked;\"";
1664
+ }
1665
+
1666
+ if ($indent) $labelclass = " class='su-indent'"; else $labelclass = '';
1667
+ echo "<div class='checkbox'><label for='$name'$labelclass><input name='$name' id='$name' type='checkbox' value='1'";
1668
+ if ($checked !== false && ($checked === true || $this->get_setting($name) === true)) echo " checked='checked'";
1669
+ if ($disabled) echo " disabled='disabled'";
1670
+ echo "$onclick /> $desc</label></div>\n";
1671
+ }
1672
+ }
1673
+
1674
+ if ($grouptext) {
1675
+ $this->admin_form_group_end(false);
1676
+ } elseif ($output_tr) {
1677
+ echo "</div>\n</div>\n";
1678
+ }
1679
+ }
1680
+
1681
+ /**
1682
+ * Outputs a single checkbox into an admin form and saves its value into the database after form submission.
1683
+ *
1684
+ * @since 1.5
1685
+ * @uses checkboxes()
1686
+ *
1687
+ * @param string $id The field/setting ID.
1688
+ * @param string $desc The checkbox's label.
1689
+ * @param mixed $grouptext The text to display in a table cell to the left of the one containing the checkbox. Optional.
1690
+ * @return string The HTML that would render the checkbox.
1691
+ */
1692
+ function checkbox($id, $desc, $grouptext = false, $args=array()) {
1693
+ $this->checkboxes(array($id => $desc), $grouptext, $args);
1694
+ }
1695
+
1696
+ /**
1697
+ * Outputs a set of radio buttons into an admin form and saves the set's value into the database after form submission.
1698
+ *
1699
+ * @since 1.5
1700
+ * @uses is_action()
1701
+ * @uses update_setting()
1702
+ * @uses admin_form_group_start()
1703
+ * @uses admin_form_group_end()
1704
+ * @uses su_esc_attr()
1705
+ * @uses get_setting()
1706
+ *
1707
+ * @param string $name The name of the set of radio buttons.
1708
+ * @param array $values The keys of this array are the radio button values, and the array values are the label strings.
1709
+ * @param string|false $grouptext The text to display in a table cell to the left of the one containing the radio buttons. Optional.
1710
+ */
1711
+ function radiobuttons($name, $values, $grouptext=false) {
1712
+
1713
+ //Save radio button setting after form submission
1714
+ if ($this->is_action('update') && isset($_POST[$name]))
1715
+ $this->update_setting($name, $_POST[$name]);
1716
+
1717
+ if ($grouptext)
1718
+ $this->admin_form_group_start($grouptext, false);
1719
+ else
1720
+ echo "<tr valign='top' class='su-admin-form-radio'>\n<td colspan='2'>\n";
1721
+
1722
+ if (is_array($values)) {
1723
+
1724
+ register_setting($this->get_module_key(), $name);
1725
+ $name = su_esc_attr($name);
1726
+
1727
+ $first = true;
1728
+ foreach ($values as $value => $desc) {
1729
+
1730
+ $value = su_esc_attr($value);
1731
+ $id = "{$name}_{$value}";
1732
+
1733
+ $current = (strcmp($this->get_setting($name), $value) == 0);
1734
+ $class = $first ? 'first' : ''; $first = false;
1735
+ if ($current) $class .= ' current-setting';
1736
+ $class = trim($class);
1737
+ if ($class) $class = " class='$class'";
1738
+
1739
+ extract($this->insert_subfield_textboxes($name, $desc));
1740
+
1741
+ echo "<div class='radio'><label for='$id'$class><input name='$name' id='$id' type='radio' value='$value'";
1742
+ if ($current) echo " checked='checked'";
1743
+ echo " /> $label";
1744
+
1745
+ if (!sustr::has($label, '</label>')) echo '</label>';
1746
+ echo "</div>\n";
1747
+ }
1748
+ }
1749
+
1750
+ if ($grouptext)
1751
+ $this->admin_form_group_end(false);
1752
+ }
1753
+
1754
+ /**
1755
+ * Outputs a dropdown into an admin form and saves the dropdown's value into the database after form submission.
1756
+ *
1757
+ * @since 3.7
1758
+ * @uses is_action()
1759
+ * @uses update_setting()
1760
+ * @uses admin_form_group_start()
1761
+ * @uses admin_form_group_end()
1762
+ * @uses su_esc_attr()
1763
+ * @uses get_setting()
1764
+ *
1765
+ * @param string $name The name of the setting which the dropdown is supposed to set.
1766
+ * @param array $values The keys of this array are the possible dropdown option values, and the array values are the option label strings.
1767
+ * @param string|false $grouptext The text to display in a table cell to the left of the one containing the dropdown. Optional.
1768
+ * @param string $text A printf-style format string in which "%s" is replaced with the dropdown. Use this to put text before or after the dropdown.
1769
+ */
1770
+ function dropdown($name, $values, $grouptext=false, $text='%s', $args=array()) {
1771
+
1772
+ $in_table = isset($args['in_table']) ? $args['in_table'] : true;
1773
+
1774
+ //Save dropdown setting after form submission
1775
+ if ($this->is_action('update') && isset($_POST[$name]))
1776
+ $this->update_setting($name, $_POST[$name]);
1777
+
1778
+ if ($grouptext)
1779
+ $this->admin_form_group_start($grouptext, false);
1780
+ elseif ($in_table)
1781
+ echo "<div class='form-group su-admin-form-dropdown'>\n<div class='col-sm-4 col-md-4'>\n";
1782
+
1783
+ if (is_array($values)) {
1784
+
1785
+ register_setting($this->get_module_key(), $name);
1786
+
1787
+ $name = su_esc_attr($name);
1788
+ $dropdown = "<select name='$name' id='$name'>\n"
1789
+ . suhtml::option_tags($values, $this->get_setting($name))
1790
+ . "</select>";
1791
+ printf($text, $dropdown);
1792
+ }
1793
+
1794
+ if ($grouptext)
1795
+ $this->admin_form_group_end();
1796
+ elseif ($in_table)
1797
+ echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
1798
+ }
1799
+
1800
+ /**
1801
+ * @since 3.0
1802
+ */
1803
+ function insert_subfield_textboxes($name, $label, $enabled = true) {
1804
+
1805
+ $pattern = '/%(d|s)({([a-z0-9_-]+)})?/';
1806
+
1807
+ if (preg_match($pattern, $label, $matches)) {
1808
+ $is_int_field = ($matches[1] == 'd');
1809
+ $sfname = $name.'_value';
1810
+
1811
+ if (isset($matches[3]))
1812
+ $sfname = $matches[3];
1813
+
1814
+ if ($this->is_action('update'))
1815
+ $sfvalue = stripslashes($_POST[$sfname]);
1816
+ else
1817
+ $sfvalue = $this->get_setting($sfname);
1818
+
1819
+ if ($is_int_field)
1820
+ $sfvalue = sustr::to_int($sfvalue);
1821
+
1822
+ if ($this->is_action('update'))
1823
+ $this->update_setting($sfname, $sfvalue);
1824
+
1825
+ if ($enabled) $disabled = ''; else $disabled = " readonly='readonly'";
1826
+
1827
+ $esfvalue = su_esc_attr($sfvalue);
1828
+ $field_html = "</label><input class='textbox subfield form-control input-sm' name='$sfname' id='$sfname' type='text' value='$esfvalue'$disabled";
1829
+ if ($is_int_field) $field_html .= " size='2' maxlength='3'";
1830
+ $field_html .= " /><label for='$name'>";
1831
+
1832
+ $label = preg_replace($pattern, $field_html, $label);
1833
+ $label = preg_replace("@<label for='$name'>$@", '', $label);
1834
+
1835
+ $onclick = " onclick=\"javascript:document.getElementById('$sfname').readOnly=!this.checked;\"";
1836
+ } else
1837
+ $onclick = '';
1838
+
1839
+ return compact('label', 'onclick');
1840
+ }
1841
+
1842
+ /**
1843
+ * Outputs a group of textboxes into an admin form, and saves the values into the database after form submission.
1844
+ * Can also display a "Reset" link next to each textbox that reverts its value to a specified default.
1845
+ *
1846
+ * @since 0.1
1847
+ * @uses is_action()
1848
+ * @uses update_setting()
1849
+ * @uses get_module_key()
1850
+ * @uses get_setting()
1851
+ *
1852
+ * @param array $textboxes An array of textboxes. (Field/setting IDs are the keys, and descriptions are the values.)
1853
+ * @param array $defaults An array of default textbox values that trigger "Reset" links. (The field/setting ID is the key, and the default value is the value.) Optional.
1854
+ * @param mixed $grouptext The text to display in a table cell to the left of the one containing the textboxes. Optional.
1855
+ */
1856
+ function textboxes($textboxes, $defaults=array(), $grouptext=false, $args=array(), $textbox_args=array()) {
1857
+
1858
+ $is_tree_parent = isset($args['is_tree_parent']) ? $args['is_tree_parent'] : false;
1859
+ $is_ec_tree = isset($args['is_ec_tree']) ? $args['is_ec_tree'] : false;
1860
+ $tree_level = isset($args['tree_level']) ? $args['tree_level'] : false;
1861
+ $disabled = isset($args['disabled']) ? $args['disabled'] : false;
1862
+ $in_table = isset($args['in_table']) ? $args['in_table'] : true;
1863
+ $help_text = isset($args['help_text']) ? $args['help_text'] : false;
1864
+ $callout = isset($args['callout']) ? $args['callout'] : false;
1865
+
1866
+ if (!$disabled && $this->is_action('update')) {
1867
+ foreach ($textboxes as $id => $title) {
1868
+ if (isset($_POST[$id]))
1869
+ $this->update_setting($id, stripslashes($_POST[$id]));
1870
+ }
1871
+ }
1872
+
1873
+ $indentattrs = $indenttoggle = $hidden = '';
1874
+ if ($tree_level !== false) {
1875
+ $indentattrs = " class='su-indent su-indent-level-{$tree_level}'";
1876
+ if ($is_ec_tree) {
1877
+ if ($is_tree_parent)
1878
+ $indenttoggle = "<span class='su-child-fields-toggle'>+</span> ";
1879
+ else
1880
+ $indenttoggle = "<span class='su-child-fields-toggle-filler'> </span> ";
1881
+
1882
+ if ($tree_level > 1)
1883
+ $hidden = " style='display: none;'";
1884
+ }
1885
+ }
1886
+
1887
+ if ($grouptext) $this->admin_form_group_start($grouptext, false);
1888
+
1889
+ foreach ($textboxes as $id => $title) {
1890
+
1891
+ $before = isset($textbox_args[$id]['before']) ? $textbox_args[$id]['before'] : '';
1892
+ $after = isset($textbox_args[$id]['after']) ? $textbox_args[$id]['after'] : '';
1893
+ $placeholder = isset($textbox_args[$id]['placeholder']) ? $textbox_args[$id]['placeholder'] : '';
1894
+
1895
+ register_setting($this->get_module_key(), $id);
1896
+ $value = su_esc_editable_html($this->get_setting($id));
1897
+ $id = su_esc_attr($id);
1898
+ $resetmessage = su_esc_attr(__('Are you sure you want to replace the textbox contents with this default value?', 'seo-ultimate'));
1899
+
1900
+ if ($callout)
1901
+ echo "<div class='bs-callout bs-callout-grey'><h4>$callout</h4></div>\n";
1902
+
1903
+ if ($grouptext)
1904
+ echo "<div class='form-group'><label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n<div class='col-sm-4 col-md-4'>\n";
1905
+ elseif ($in_table && strpos($title, '</a>') === false)
1906
+ echo "<div class='form-group'$indentattrs$hidden>\n<label class='col-sm-4 col-md-4 control-label' for='$id'><span class='su-field-label-text'>$title</span></label>\n<div class='col-sm-4 col-md-4'>\n";
1907
+ elseif ($in_table)
1908
+ echo "<div class='form-group'$indentattrs$hidden>\n<label class='col-sm-4 col-md-4 control-label' for='$id'><span class='su-field-label-text'>$title</span></label>\n<div class='col-sm-4 col-md-4'>\n";
1909
+
1910
+ echo $before;
1911
+
1912
+ echo "<input name='$id' id='$id' type='text' value='$value' class='form-control input-sm regular-text' ";
1913
+
1914
+ if ($placeholder) {
1915
+ $a_placeholder = su_esc_attr($placeholder);
1916
+ echo "placeholder='$placeholder' ";
1917
+ }
1918
+
1919
+ if ($disabled)
1920
+ echo "disabled='disabled' />";
1921
+ elseif (isset($defaults[$id])) {
1922
+ $default = su_esc_editable_html($defaults[$id]);
1923
+ echo "onkeyup=\"javascript:su_textbox_value_changed(this, '$default', '{$id}_reset')\" />";
1924
+ echo "&nbsp;<a href=\"#\" id=\"{$id}_reset\" onclick=\"javascript:su_reset_textbox('$id', '$default', '$resetmessage', this); return false;\"";
1925
+ if ($default == $value) echo ' class="hidden"';
1926
+ echo ">";
1927
+ _e('Reset', 'seo-ultimate');
1928
+ echo "</a>";
1929
+
1930
+ if (isset($args['open_url_value_link']))
1931
+ echo ' |';
1932
+ } else {
1933
+ echo "/>";
1934
+ }
1935
+
1936
+ if (isset($args['open_url_value_link'])) {
1937
+ echo " <a href='#' onclick=\"javascript:window.open(document.getElementById('$id').value);return false;\">";
1938
+ echo su_esc_html($args['open_url_value_link']);
1939
+ echo '</a>';
1940
+ }
1941
+
1942
+ echo $after;
1943
+
1944
+ if ($grouptext)
1945
+ echo "</div>\n";
1946
+ elseif ($in_table)
1947
+ echo "</div>\n";
1948
+
1949
+ if ($help_text)
1950
+ echo "<div class='col-sm-4 col-md-4'>$help_text</div>\n</div>\n";
1951
+ else
1952
+ echo "<div class='col-sm-4 col-md-4'></div>\n</div>\n";
1953
+ }
1954
+
1955
+ if ($grouptext) $this->admin_form_group_end(false);
1956
+ }
1957
+
1958
+ /**
1959
+ * Outputs a single textbox into an admin form and saves its value into the database after form submission.
1960
+ *
1961
+ * @since 0.1
1962
+ * @uses textboxes()
1963
+ *
1964
+ * @param string $id The field/setting ID.
1965
+ * @param string $title The label of the HTML element.
1966
+ * @param string|false $default The default textbox value. Setting this will trigger a "Reset" link. Optional.
1967
+ * @return string The HTML that would render the textbox.
1968
+ */
1969
+ function textbox($id, $title, $default=false, $grouptext=false, $args=array(), $textbox_args=array()) {
1970
+ if ($default === false) $default = array(); else $default = array($id => $default);
1971
+ $this->textboxes(array($id => $title), $default, $grouptext, $args, array($id => $textbox_args));
1972
+ }
1973
+
1974
+ /**
1975
+ * Outputs a group of textareas into an admin form, and saves the values into the database after form submission.
1976
+ *
1977
+ * @since 0.1
1978
+ * @uses is_action()
1979
+ * @uses update_setting()
1980
+ * @uses get_module_key()
1981
+ * @uses get_setting()
1982
+ *
1983
+ * @param array $textareas An array of textareas. (Field/setting IDs are the keys, and descriptions are the values.)
1984
+ * @param int $rows The value of the textareas' rows attribute.
1985
+ * @param int $cols The value of the textareas' cols attribute.
1986
+ */
1987
+ function textareas($textareas, $rows = 5, $cols = 30, $args=array()) {
1988
+
1989
+ $disabled = isset($args['disabled']) ? $args['disabled'] : false;
1990
+
1991
+ if (!$disabled && $this->is_action('update')) {
1992
+ foreach ($textareas as $id => $title) {
1993
+ if (isset($_POST[$id]))
1994
+ $this->update_setting($id, stripslashes($_POST[$id]));
1995
+ }
1996
+ }
1997
+
1998
+ foreach ($textareas as $id => $title) {
1999
+ register_setting($this->get_module_key(), $id);
2000
+ $value = su_esc_editable_html($this->get_setting($id));
2001
+ $id = su_esc_attr($id);
2002
+
2003
+ echo "<div class='form-group'>\n";
2004
+ if ($title) echo "<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n";
2005
+ echo "<div class='col-sm-4 col-md-4'>";
2006
+ echo "<textarea name='$id' id='$id' type='text' class='form-control regular-text' cols='$cols' rows='$rows'";
2007
+ if ($disabled) echo " disabled='disabled'";
2008
+ echo ">$value</textarea>";
2009
+ echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2010
+ }
2011
+ }
2012
+
2013
+ /**
2014
+ * Outputs a single textarea into an admin form and saves its value into the database after form submission.
2015
+ *
2016
+ * @since 0.1
2017
+ * @uses textareas()
2018
+ *
2019
+ * @param string $id The field/setting ID.
2020
+ * @param string $title The label of the HTML element.
2021
+ * @param int $rows The value of the textarea's rows attribute.
2022
+ * @param int $cols The value of the textarea's cols attribute.
2023
+ * @return string The HTML that would render the textarea.
2024
+ */
2025
+ function textarea($id, $title = '', $rows = 5, $cols = 30) {
2026
+ $this->textareas(array($id => $title), $rows, $cols);
2027
+ }
2028
+
2029
+ /**
2030
+ * @since 7.3
2031
+ */
2032
+ function jlsuggest_boxes($jls_boxes) {
2033
+
2034
+ if ($this->is_action('update')) {
2035
+ foreach ($jls_boxes as $jls_box) {
2036
+
2037
+ if (!isset($jls_box['id']))
2038
+ continue;
2039
+
2040
+ $id = $jls_box['id'];
2041
+
2042
+ if (isset($_POST[$id]))
2043
+ $this->update_setting($id, stripslashes($_POST[$id]));
2044
+ }
2045
+ }
2046
+
2047
+ foreach ($jls_boxes as $jls_box) {
2048
+
2049
+ if (!isset($jls_box['id']))
2050
+ continue;
2051
+
2052
+ $jls_box = wp_parse_args($jls_box, array(
2053
+ 'title' => ''
2054
+ , 'params' => ''
2055
+ ));
2056
+
2057
+ extract($jls_box, EXTR_SKIP);
2058
+
2059
+ register_setting($this->get_module_key(), $id);
2060
+
2061
+ echo "<div class='form-group'>\n";
2062
+ if ($title) echo "<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n";
2063
+ echo "<div class='col-sm-4 col-md-4'>";
2064
+ echo $this->get_jlsuggest_box($id, $this->get_setting($id), $params);
2065
+ echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2066
+ }
2067
+ }
2068
+
2069
+ /**
2070
+ * @since 7.3
2071
+ */
2072
+ function jlsuggest_box($id, $title, $params='') {
2073
+ $this->jlsuggest_boxes(array(compact('id', 'title', 'params')));
2074
+ }
2075
+ /**
2076
+ * @since 7.6.3
2077
+ */
2078
+ function medialib_boxes($media_boxes) {
2079
+
2080
+ if ($this->is_action('update')) {
2081
+ foreach ($media_boxes as $media_box) {
2082
+
2083
+ if (!isset($media_box['id']))
2084
+ continue;
2085
+
2086
+ $id = $media_box['id'];
2087
+
2088
+ if (isset($_POST[$id]))
2089
+ $this->update_setting($id, stripslashes($_POST[$id]));
2090
+ }
2091
+ }
2092
+
2093
+ foreach ($media_boxes as $media_box) {
2094
+
2095
+ if (!isset($media_box['id']))
2096
+ continue;
2097
+
2098
+ $media_box = wp_parse_args($media_box, array(
2099
+ 'title' => ''
2100
+ , 'params' => ''
2101
+ ));
2102
+
2103
+ extract($media_box, EXTR_SKIP);
2104
+
2105
+ register_setting($this->get_module_key(), $id);
2106
+
2107
+ echo "<div class='form-group'>\n";
2108
+ if ($title) echo "<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n";
2109
+ echo "<div class='col-sm-4 col-md-4'>";
2110
+ echo "<div class='input-group'>
2111
+ <input id='".su_esc_attr($id)."' name='".su_esc_attr($id)."' type='text' class='wpu-image form-control' size='40' value='".$this->get_setting($id)."'>
2112
+ <span class='input-group-btn'>
2113
+ <span class='btn btn-custom btn-file wpu-media-upload'>
2114
+ <i class='fa fa-upload'></i> Upload Image <input type='file'>
2115
+ </span>
2116
+ </span>
2117
+ </div>";
2118
+ echo "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2119
+ }
2120
+ }
2121
+
2122
+ /**
2123
+ * @since 7.6.3
2124
+ */
2125
+ function medialib_box($id, $title, $params='') {
2126
+ $this->medialib_boxes(array(compact('id', 'title', 'params')));
2127
+ }
2128
+
2129
+ /********** ADMIN SECURITY FUNCTIONS **********/
2130
+
2131
+ /**
2132
+ * Determines if a particular nonce-secured admin action is being executed.
2133
+ *
2134
+ * @since 0.1
2135
+ * @uses SEO_Ultimate::key_to_hook()
2136
+ * @uses get_module_key()
2137
+ * @uses nonce_validates()
2138
+ *
2139
+ * @param string $action The name of the action to check.
2140
+ * @return bool Whether or not the action is being executed.
2141
+ */
2142
+ function is_action($action) {
2143
+ if (!isset($_GET['object']) || !($object = $_GET['object'])) $object = false;
2144
+ return (
2145
+ !empty($_GET['page'])
2146
+ && (
2147
+ ( strcasecmp($_GET['page'], $this->plugin->key_to_hook($this->get_module_key())) == 0 ) //Is $this module being shown?
2148
+ || ( strlen($this->get_parent_module()) && strcasecmp($_GET['page'], $this->plugin->key_to_hook($this->get_parent_module())) == 0) //Is the parent module being shown?
2149
+ )
2150
+ && (
2151
+ (!empty($_GET['action']) && $_GET['action'] == $action)
2152
+ || (!empty($_POST['action']) && $_POST['action'] == $action)
2153
+ ) //Is this $action being executed?
2154
+ && $this->nonce_validates($action, $object) //Is the nonce valid?
2155
+ );
2156
+ }
2157
+
2158
+ /**
2159
+ * Determines whether a nonce is valid.
2160
+ *
2161
+ * @since 0.1
2162
+ * @uses get_nonce_handle()
2163
+ *
2164
+ * @param string $action The name of the action.
2165
+ * @param mixed $id The ID of the object being acted upon. Optional.
2166
+ * @return bool Whether or not the nonce is valid.
2167
+ */
2168
+ function nonce_validates($action, $id = false) {
2169
+ return check_admin_referer($this->get_nonce_handle($action, $id));
2170
+ }
2171
+
2172
+ /**
2173
+ * Generates a unique name for a nonce.
2174
+ *
2175
+ * @since 0.1
2176
+ * @uses get_parent_module()
2177
+ * @uses get_module_key()
2178
+ * @uses SU_PLUGIN_NAME
2179
+ *
2180
+ * @param string $action The name of the action.
2181
+ * @param mixed $id The ID of the object being acted upon. Optional.
2182
+ * @return The handle to use for the nonce.
2183
+ */
2184
+ function get_nonce_handle($action, $id = false) {
2185
+
2186
+ $key = $this->get_parent_module();
2187
+ if (!$key || !$this->plugin->module_exists($key)) $key = $this->get_module_key();
2188
+
2189
+ $hook = $this->plugin->key_to_hook($key);
2190
+
2191
+ if (strcmp($action, 'update') == 0) {
2192
+ //We use the settings_fields() function, which outputs a nonce in this particular format.
2193
+ return "$hook-options";
2194
+ } else {
2195
+ if ($id) $id = '-'.md5($id); else $id = '';
2196
+ $handle = SU_PLUGIN_NAME."-$hook-$action$id";
2197
+ return strtolower(str_replace(' ', '-', $handle));
2198
+ }
2199
+ }
2200
+
2201
+ /**
2202
+ * Returns a GET-action URL with an appended nonce.
2203
+ *
2204
+ * @since 0.1
2205
+ * @uses get_module_key()
2206
+ * @uses get_nonce_handle()
2207
+ *
2208
+ * @param string $action The name of the action.
2209
+ * @param mixed $id The ID of the object being acted upon. Optional.
2210
+ * @return The URL to use in an <a> tag.
2211
+ */
2212
+ function get_nonce_url($action, $object=false) {
2213
+ $action = urlencode($action);
2214
+ if ($object) $objectqs = '&object='.urlencode($object); else $objectqs = '';
2215
+
2216
+ $hook = $this->plugin->key_to_hook($this->get_module_or_parent_key());
2217
+
2218
+ //We don't need to escape ampersands since wp_nonce_url will do that for us
2219
+ return wp_nonce_url("?page=$hook&action=$action$objectqs",
2220
+ $this->get_nonce_handle($action, $object));
2221
+ }
2222
+
2223
+
2224
+ /********** ADMIN MESSAGE FUNCTIONS **********/
2225
+
2226
+ /**
2227
+ * Print a message (and any previously-queued messages) right away.
2228
+ *
2229
+ * @since 0.1
2230
+ * @uses queue_message()
2231
+ * @uses print_messages()
2232
+ *
2233
+ * @param string $type The message's type. Valid values are success, error, warning, and info.
2234
+ * @param string $message The message text.
2235
+ */
2236
+ function print_message($type, $message) {
2237
+ $this->queue_message($type, $message);
2238
+ $this->print_messages();
2239
+ }
2240
+
2241
+ /**
2242
+ * Adds a message to the queue.
2243
+ *
2244
+ * @since 0.1
2245
+ * @uses $messages
2246
+ *
2247
+ * @param string $type The message's type. Valid values are success, error, warning, and info.
2248
+ * @param string $message The message text.
2249
+ */
2250
+ function queue_message($type, $message) {
2251
+ $this->messages[$type][] = $message;
2252
+ }
2253
+
2254
+ /**
2255
+ * Prints all queued messages and flushes the queue.
2256
+ *
2257
+ * @since 0.1
2258
+ * @uses $messages
2259
+ */
2260
+ function print_messages() {
2261
+ foreach ($this->messages as $type => $messages) {
2262
+ $messages = implode('<br />', $messages);
2263
+ if ($messages) {
2264
+ $type = su_esc_attr($type);
2265
+ echo "<div class='su-message'><p class='su-$type'>$messages</p></div>\n";
2266
+ }
2267
+ }
2268
+
2269
+ $this->messages = array();
2270
+ }
2271
+
2272
+ /**
2273
+ * Prints a mini-style message.
2274
+ *
2275
+ * @since 2.1
2276
+ */
2277
+ function print_mini_message($type, $message) {
2278
+ $type = su_esc_attr($type);
2279
+ echo "<div class='su-status su-$type'>$message</div>";
2280
+ }
2281
+
2282
+ /********** ADMIN META FUNCTIONS **********/
2283
+
2284
+ /**
2285
+ * Gets a specified meta value of the current post (i.e. the post currently being edited in the admin,
2286
+ * the post being shown, the post now in the loop, or the post with specified ID).
2287
+ *
2288
+ * @since 0.1
2289
+ *
2290
+ * @param string $key The meta key to fetch.
2291
+ * @param mixed $id The ID number of the post/page.
2292
+ * @return string The meta value requested.
2293
+ */
2294
+ function get_postmeta($key, $id=false) {
2295
+
2296
+ if (!$id) {
2297
+ //This code is different from suwp::get_post_id();
2298
+ if (is_admin()) {
2299
+ $id = empty($_REQUEST['post']) ? false : intval($_REQUEST['post']);
2300
+ global $post;
2301
+ } elseif (in_the_loop()) {
2302
+ $id = intval(get_the_ID());
2303
+ global $post;
2304
+ } elseif (is_singular()) {
2305
+ global $wp_query;
2306
+ $id = $wp_query->get_queried_object_id();
2307
+ $post = $wp_query->get_queried_object();
2308
+ }
2309
+ }
2310
+
2311
+ if ($id) {
2312
+
2313
+ if (isset($post) && $post)
2314
+ $_post = $post;
2315
+ else
2316
+ $_post = get_post($id);
2317
+
2318
+ $value = get_post_meta($id, "_su_$key", true);
2319
+ $value = apply_filters("su_get_postmeta", $value, $key, $_post);
2320
+ $value = apply_filters("su_get_postmeta-$key", $value, $key, $_post);
2321
+ } else
2322
+ $value = '';
2323
+
2324
+ return $value;
2325
+ }
2326
+
2327
+ /**
2328
+ * Generates the HTML for multiple post meta textboxes.
2329
+ *
2330
+ * @since 0.1
2331
+ * @uses get_postmeta()
2332
+ *
2333
+ * @param array $textboxes An array of textboxes. (Field/setting IDs are the keys, and descriptions are the values.)
2334
+ * @return string The HTML that would render the textboxes.
2335
+ */
2336
+ function get_postmeta_textboxes($textboxes, $textbox_args=array(), $grouptext=false) {
2337
+
2338
+ $html = '';
2339
+
2340
+ if ($grouptext) {
2341
+ $h_grouptext = esc_html($grouptext);
2342
+ $html = "<div class='form-group su textbox'>\n<h4 class='col-sm-4 col-md-4 control-label'>$h_grouptext</h4>\n<div class='col-sm-4 col-md-4'></div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2343
+ }
2344
+
2345
+ foreach ($textboxes as $id => $title) {
2346
+
2347
+ $type = isset($textbox_args[$id]['type']) ? $textbox_args[$id]['type'] : 'text';
2348
+ $input_clss = ($type == 'text') ? 'input-sm ' : '';
2349
+
2350
+ register_setting('seo-ultimate', $id);
2351
+ $value = su_esc_editable_html($this->get_postmeta($id));
2352
+ $id = "_su_".su_esc_attr($id);
2353
+
2354
+ $e_title = su_esc_attr($title);
2355
+
2356
+ $html = "<div class='form-group su textbox'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n<div class='col-sm-4 col-md-4'><input name='$id' id='$id' type='$type' value='$value' class='"
2357
+ . $input_clss."form-control regular-text' tabindex='2' />\n"
2358
+ . "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2359
+ }
2360
+
2361
+ if ($grouptext) {
2362
+ $h_grouptext = esc_html($grouptext);
2363
+ //$html .= "</table></td>\n</tr>\n";
2364
+ }
2365
+
2366
+ return $html;
2367
+ }
2368
+
2369
+ /**
2370
+ * Generates the HTML for a single post meta textbox.
2371
+ *
2372
+ * @since 0.1
2373
+ * @uses get_postmeta_textboxes()
2374
+ *
2375
+ * @param string $id The ID of the HTML element.
2376
+ * @param string $title The label of the HTML element.
2377
+ * @return string The HTML that would render the textbox.
2378
+ */
2379
+ function get_postmeta_textbox($id, $title, $args=array()) {
2380
+ return $this->get_postmeta_textboxes(array($id => $title), array($id => $args));
2381
+ }
2382
+
2383
+ /**
2384
+ * Generates the HTML for multiple post meta textareas.
2385
+ *
2386
+ * @since 3.9
2387
+ * @uses get_postmeta()
2388
+ *
2389
+ * @param array $textareas An array of textareas. (Field/setting IDs are the keys, and descriptions are the values.)
2390
+ * @return string The HTML that would render the textareas.
2391
+ */
2392
+ function get_postmeta_textareas($textareas) {
2393
+
2394
+ $html = '';
2395
+
2396
+ foreach ($textareas as $id => $title) {
2397
+
2398
+ register_setting('seo-ultimate', $id);
2399
+ $value = su_esc_editable_html($this->get_postmeta($id));
2400
+ $id = "_su_".su_esc_attr($id);
2401
+
2402
+ $html = "<div class='form-group su textarea'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n<div class='col-sm-4 col-md-4'><textarea name='$id' id='$id' class='form-control regular-text' tabindex='2' cols='60' rows='3'>$value</textarea>\n"
2403
+ ."</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2404
+ }
2405
+
2406
+ return $html;
2407
+ }
2408
+
2409
+ /**
2410
+ * Generates the HTML for a single post meta textarea.
2411
+ *
2412
+ * @since 3.9
2413
+ * @uses get_postmeta_textareas()
2414
+ *
2415
+ * @param string $id The ID of the HTML element.
2416
+ * @param string $title The label of the HTML element.
2417
+ * @return string The HTML that would render the textarea.
2418
+ */
2419
+ function get_postmeta_textarea($id, $title) {
2420
+ return $this->get_postmeta_textareas(array($id => $title));
2421
+ }
2422
+
2423
+ /**
2424
+ * Generates the HTML for a group of post meta checkboxes.
2425
+ *
2426
+ * @since 0.1
2427
+ * @uses get_module_key()
2428
+ * @uses get_postmeta()
2429
+ *
2430
+ * @param array $checkboxes An array of checkboxes. (Field/setting IDs are the keys, and descriptions are the values.)
2431
+ * @param string $grouptext The text to display in a table cell to the left of the one containing the checkboxes.
2432
+ */
2433
+ function get_postmeta_checkboxes($checkboxes, $grouptext) {
2434
+
2435
+ $valign = (is_array($checkboxes) && count($checkboxes) > 1) ? 'top' : 'middle';
2436
+ $html = "<div class='form-group su checkboxes'>\n<label class='col-sm-4 col-md-4 control-label'>$grouptext</label>\n<div class='col-sm-4 col-md-4'>\n";
2437
+
2438
+ if (is_array($checkboxes)) {
2439
+ foreach ($checkboxes as $name => $desc) {
2440
+
2441
+ register_setting('seo-ultimate', $name);
2442
+ $checked = ($this->get_postmeta($name) == 1);
2443
+ $name = "_su_".su_esc_attr($name);
2444
+
2445
+ $html .= "<div class='checkbox'><label for='$name'><input name='$name' id='$name' type='checkbox' tabindex='2' value='1'";
2446
+ if ($checked) $html .= " checked='checked'";
2447
+ $html .= " /> $desc</label></div>\n";
2448
+ }
2449
+ }
2450
+
2451
+ $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2452
+
2453
+ return $html;
2454
+ }
2455
+
2456
+ /**
2457
+ * Generates the HTML for a single post meta checkbox.
2458
+ *
2459
+ * @since 0.1
2460
+ * @uses get_postmeta_checkboxes()
2461
+ *
2462
+ * @param string $id The ID of the HTML element.
2463
+ * @param string $title The label of the HTML element.
2464
+ * @param string $grouptext The text to display in a table cell to the left of the one containing the checkboxes.
2465
+ * @return string The HTML that would render the textbox.
2466
+ */
2467
+ function get_postmeta_checkbox($id, $title, $grouptext) {
2468
+ return $this->get_postmeta_checkboxes(array($id => $title), $grouptext);
2469
+ }
2470
+
2471
+ /**
2472
+ * Generates the HTML for a single <select> post meta dropdown.
2473
+ *
2474
+ * @since 2.5
2475
+ * @uses get_module_key()
2476
+ * @uses get_postmeta()
2477
+ *
2478
+ * @param string $name The name of the <select> element.
2479
+ * @param array $options An array of options, where the array keys are the <option> values and the array values are the labels (<option> contents).
2480
+ * @param string $grouptext The text to display in a table cell to the left of the one containing the dropdown.
2481
+ * @return string $html
2482
+ */
2483
+ function get_postmeta_dropdown($name, $options, $grouptext) {
2484
+
2485
+ register_setting('seo-ultimate', $name);
2486
+ $current = $this->get_postmeta($name);
2487
+ if ($current === '') {
2488
+ $current = reset($options);
2489
+ }
2490
+ $name = "_su_".su_esc_attr($name);
2491
+
2492
+ $html = "<div class='form-group su dropdown'>\n<label class='col-sm-4 col-md-4 control-label' for='$name'>$grouptext</label>\n<div class='col-sm-4 col-md-4'>\n";
2493
+ $html .= "<select name='$name' id='$name' onchange='javascript:su_toggle_select_children(this)'>\n";
2494
+ $html .= suhtml::option_tags($options, $current);
2495
+ $html .= "</select>\n";
2496
+ $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'></div>\n</div>\n";
2497
+
2498
+ return $html;
2499
+ }
2500
+
2501
+ /**
2502
+ * Generates the HTML for multiple post meta JLSuggest boxes.
2503
+ *
2504
+ * @since 7.3
2505
+ *
2506
+ * @param array $jls_boxes An array of JLSuggest boxes. (Field/setting IDs are the keys, and descriptions are the values.)
2507
+ * @return string The HTML for the JLSuggest boxes.
2508
+ */
2509
+ function get_postmeta_jlsuggest_boxes($jls_boxes) {
2510
+
2511
+ $html = '';
2512
+
2513
+ foreach ($jls_boxes as $jls_box) {
2514
+
2515
+ if (!isset($jls_box['id']) || !isset($jls_box['title']))
2516
+ continue;
2517
+
2518
+ $id = $jls_box['id'];
2519
+ $title = $jls_box['title'];
2520
+ $params = isset($jls_box['params']) ? $jls_box['params'] : false;
2521
+
2522
+ register_setting('seo-ultimate', $id);
2523
+ $value = su_esc_editable_html($this->get_postmeta($id));
2524
+ $id = "_su_".su_esc_attr($id);
2525
+
2526
+ $html .= "<div class='form-group su jlsuggestbox'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n"
2527
+ ."<div class='col-sm-4 col-md-4 su'>";
2528
+ $html .= $this->get_jlsuggest_box($id, $value, $params);
2529
+ $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2530
+ }
2531
+
2532
+ return $html;
2533
+ }
2534
+
2535
+ /**
2536
+ * Generates the HTML for a single post meta JLSuggest box.
2537
+ *
2538
+ * @since 7.3
2539
+ * @uses get_postmeta_jlsuggest_boxes()
2540
+ *
2541
+ * @param string $id The ID of the HTML element.
2542
+ * @param string $title The label of the HTML element.
2543
+ * @param string $params The value of the su:params attribute of the JLSuggest box (optional).
2544
+ * @return string The HTML that would render the JLSuggest box.
2545
+ */
2546
+ function get_postmeta_jlsuggest_box($id, $title, $params=false) {
2547
+ $jls_box = compact('id', 'title', 'params');
2548
+ return $this->get_postmeta_jlsuggest_boxes(array($jls_box));
2549
+ }
2550
+
2551
+ /**
2552
+ * Generates the HTML for multiple post meta mediaupload boxes.
2553
+ *
2554
+ * @since 7.6.3
2555
+ *
2556
+ * @param array $media_boxes An array of mediaupload boxes. (Field/setting IDs are the keys, and descriptions are the values.)
2557
+ * @return string The HTML for the mediaupload boxes.
2558
+ */
2559
+ function get_postmeta_medialib_boxes($media_boxes) {
2560
+
2561
+ $html = '';
2562
+
2563
+ foreach ($media_boxes as $media_box) {
2564
+
2565
+ if (!isset($media_box['id']) || !isset($media_box['title']))
2566
+ continue;
2567
+
2568
+ $id = $media_box['id'];
2569
+ $title = $media_box['title'];
2570
+
2571
+ register_setting('seo-ultimate', $id);
2572
+ $value = su_esc_editable_html($this->get_postmeta($id));
2573
+ $id = "_su_".su_esc_attr($id);
2574
+
2575
+ $html .= "<div class='form-group su'>\n<label class='col-sm-4 col-md-4 control-label' for='$id'>$title</label>\n"
2576
+ ."<div class='col-sm-4 col-md-4 su'>";
2577
+ $html .= "<div class='input-group'>
2578
+ <input id='".su_esc_attr($id)."' name='".su_esc_attr($id)."' type='text' class='wpu-image form-control' size='40' value='".$value."'>
2579
+ <span class='input-group-btn'>
2580
+ <span class='btn btn-custom btn-file wpu-media-upload'>
2581
+ <i class='fa fa-upload'></i> Upload Image <input type='file'>
2582
+ </span>
2583
+ </span>
2584
+ </div>";
2585
+ $html .= "</div>\n<div class='col-sm-4 col-md-4 help-text'>\n</div>\n</div>\n";
2586
+ }
2587
+
2588
+ return $html;
2589
+ }
2590
+
2591
+ /**
2592
+ * Generates the HTML for a single post meta mediaupload box.
2593
+ *
2594
+ * @since 7.6.3
2595
+ * @uses get_postmeta_medialib_boxes()
2596
+ *
2597
+ * @param string $id The ID of the HTML element.
2598
+ * @param string $title The label of the HTML element.
2599
+ * @return string The HTML that would render the mediaupload box.
2600
+ */
2601
+ function get_postmeta_medialib_box($id, $title) {
2602
+ $media_box = compact('id', 'title');
2603
+ return $this->get_postmeta_medialib_boxes(array($media_box));
2604
+ }
2605
+
2606
+ /**
2607
+ * Turns a <tr> into a post meta subsection.
2608
+ *
2609
+ * @since 2.5
2610
+ * @uses get_postmeta
2611
+ *
2612
+ * @param string $field
2613
+ * @param string $value
2614
+ * @param string $html
2615
+ * @return string $html
2616
+ */
2617
+ function get_postmeta_subsection($field, $value, $html) {
2618
+ $hidden = ($this->get_postmeta($field) == $value) ? '' : ' hidden';
2619
+
2620
+ $field = su_esc_attr($field);
2621
+ $value = su_esc_attr($value);
2622
+ $html = str_replace("<div class='form-group ", "<div class='form-group su_{$field}_{$value}_subsection$hidden ", $html);
2623
+ return $html;
2624
+ }
2625
+
2626
+ /**
2627
+ * Gets a specified meta value of the current term.
2628
+ *
2629
+ * @since 5.4
2630
+ *
2631
+ * @param string $key The database setting where the metadata is stored. The function will add a "taxonomy_" prefix.
2632
+ * @param mixed $id The ID number of the post/page.
2633
+ * @return string The meta value requested.
2634
+ */
2635
+ function get_termmeta($key, $id=false, $module=false) {
2636
+
2637
+ global $wp_query;
2638
+
2639
+ if (!$id && suwp::is_tax())
2640
+ $id = $wp_query->get_queried_object_id();
2641
+
2642
+ if (!$id)
2643
+ return null;
2644
+
2645
+ $tax_meta = $this->get_setting(sustr::startwith($key, 'taxonomy_'), array(), $module);
2646
+
2647
+ if (is_array($tax_meta) && isset($tax_meta[$id]))
2648
+ return $tax_meta[$id];
2649
+
2650
+ return null;
2651
+ }
2652
+
2653
+ /********** CRON FUNCTION **********/
2654
+
2655
+ /**
2656
+ * Creates a cron job if it doesn't already exists, and ensures it runs at the scheduled time.
2657
+ * Should be called in a module's init() function.
2658
+ *
2659
+ * @since 0.1
2660
+ * @uses get_module_key()
2661
+ *
2662
+ * @param string $function The name of the module function that should be run.
2663
+ * @param string $recurrence How often the job should be run. Valid values are hourly, twicedaily, and daily.
2664
+ */
2665
+ function cron($function, $recurrence) {
2666
+
2667
+ $mk = $this->get_module_key();
2668
+
2669
+ $hook = "su-$mk-".str_replace('_', '-', $function);
2670
+ $start = time();
2671
+
2672
+ if (wp_next_scheduled($hook) === false) {
2673
+ //This is a new cron job
2674
+
2675
+ //Schedule the event
2676
+ wp_schedule_event($start, $recurrence, $hook);
2677
+
2678
+ //Make a record of it
2679
+ $psdata = (array)get_option('seo_ultimate', array());
2680
+ $psdata['cron'][$mk][$function] = array($hook, $start, $recurrence);
2681
+ update_option('seo_ultimate', $psdata);
2682
+
2683
+ //Run the event now
2684
+ call_user_func(array($this, $function));
2685
+ }
2686
+
2687
+ add_action($hook, array(&$this, $function));
2688
+ }
2689
+
2690
+ /********** JLSUGGEST **********/
2691
+
2692
+ /**
2693
+ * Initializes JLSuggest.
2694
+ * Must be called in the admin_page_init() function of the module that wants to use JLSuggest.
2695
+ *
2696
+ * @since 6.0
2697
+ * @uses jlsuggest_xml_ns()
2698
+ * @uses SEO_Ultimate::queue_js()
2699
+ * @uses SEO_Ultimate::queue_css()
2700
+ */
2701
+ function jlsuggest_init() {
2702
+ add_action('admin_xml_ns', array(&$this, 'jlsuggest_xml_ns'));
2703
+ $this->plugin->queue_js ('includes', 'encoder');
2704
+ $this->plugin->queue_js ('includes/jlsuggest', 'jlsuggest');
2705
+ $this->plugin->queue_css('includes/jlsuggest', 'jlsuggest');
2706
+ }
2707
+
2708
+ /**
2709
+ * Outputs the SEO Ultimate XMLNS used by JLSuggest.
2710
+ *
2711
+ * @since 6.0
2712
+ */
2713
+ function jlsuggest_xml_ns() {
2714
+ echo ' xmlns:su="http://johnlamansky.com/xmlns/seo-ultimate" ';
2715
+ }
2716
+
2717
+ /**
2718
+ * Explodes a JLSuggest database string into an array with the destination type and the destination ID.
2719
+ *
2720
+ * @since 6.0
2721
+ *
2722
+ * @param $valstr The database string, e.g. http://example.com or obj_posttype_post/1
2723
+ * @return array
2724
+ */
2725
+ function jlsuggest_value_explode($valstr) {
2726
+
2727
+ if (is_array($valstr)) {
2728
+
2729
+ if (count($valstr) == 3)
2730
+ return $valstr;
2731
+
2732
+ } elseif (is_string($valstr)) {
2733
+
2734
+ if (sustr::startswith($valstr, 'obj_')) {
2735
+ $valstr = sustr::ltrim_str($valstr, 'obj_');
2736
+
2737
+ $valarr = explode('/', $valstr);
2738
+ if (count($valarr) == 2) {
2739
+ $valarr_type = explode('_', $valarr[0], 2);
2740
+ if (count($valarr_type) == 2)
2741
+ return array($valarr_type[0], $valarr_type[1], $valarr[1]);
2742
+ else
2743
+ return array($valarr[0], null, $valarr[1]);
2744
+ } else
2745
+ return array($valstr, null, null);
2746
+ } else {
2747
+ return array('url', null, $valstr);
2748
+ }
2749
+ }
2750
+
2751
+ return array('url', null, '');
2752
+ }
2753
+
2754
+ /**
2755
+ * Returns the HTML code for a JLSuggest textbox
2756
+ *
2757
+ * @since 6.0
2758
+ *
2759
+ * @param string $name The value of the textbox's name/ID attributes
2760
+ * @param string $value The current database string associated with this textbox
2761
+ */
2762
+ function get_jlsuggest_box($name, $value, $params='', $placeholder='') {
2763
+
2764
+ list($to_genus, $to_type, $to_id) = $this->jlsuggest_value_explode($value);
2765
+
2766
+ $text_dest = '';
2767
+ $disabled = false;
2768
+
2769
+ switch ($to_genus) {
2770
+
2771
+ case 'posttype':
2772
+ $selected_post = get_post($to_id);
2773
+ if ($selected_post) {
2774
+ $selected_post_type = get_post_type_object($selected_post->post_type);
2775
+ $text_dest = $selected_post->post_title . '<span class="type">&nbsp;&mdash;&nbsp;'.$selected_post_type->labels->singular_name.'</span>';
2776
+ } else {
2777
+ $selected_post_type = get_post_type_object($to_type);
2778
+ if ($selected_post_type)
2779
+ $text_dest = sprintf(__('A Deleted %s', 'seo-ultimate'), $selected_post_type->labels->singular_name);
2780
+ else
2781
+ $text_dest = __('A Deleted Post', 'seo-ultimate');
2782
+ $text_dest = '<span class="type">' . $text_dest . '</span>';
2783
+ $disabled = true;
2784
+ }
2785
+ break;
2786
+ case 'taxonomy':
2787
+ if ($selected_taxonomy = get_taxonomy($to_type)) {
2788
+ if ($selected_term = get_term($to_id, $selected_taxonomy->name)) {
2789
+ $text_dest = $selected_term->name . '<span class="type">&nbsp;&mdash;&nbsp;'.$selected_taxonomy->labels->singular_name.'</span>';
2790
+ } else {
2791
+ $text_dest = sprintf(__('A Deleted %s', 'seo-ultimate'), $selected_taxonomy->labels->singular_name);
2792
+ $text_dest = '<span class="type">' . $text_dest . '</span>';
2793
+ $disabled = true;
2794
+ }
2795
+ } else {
2796
+ $text_dest = __('A Deleted Term', 'seo-ultimate');
2797
+ $text_dest = '<span class="type">' . $text_dest . '</span>';
2798
+ $disabled = true;
2799
+ }
2800
+ break;
2801
+ case 'home':
2802
+ $text_dest = __('Blog Homepage', 'seo-ultimate');
2803
+ break;
2804
+ case 'author':
2805
+ if (is_user_member_of_blog($to_id)) {
2806
+ $selected_author = get_userdata($to_id);
2807
+ $text_dest = $selected_author->user_login . '<span class="type">&nbsp;&mdash;&nbsp;'.__('Author', 'seo-ultimate').'</span>';
2808
+ } else {
2809
+ $text_dest = __('A Deleted User', 'seo-ultimate');
2810
+ $text_dest = '<span class="type">' . $text_dest . '</span>';
2811
+ $disabled = true;
2812
+ }
2813
+ break;
2814
+ case 'internal-link-alias':
2815
+
2816
+ $alias_dir = $this->get_setting('alias_dir', 'go', 'internal-link-aliases');
2817
+ $aliases = $this->get_setting('aliases', array(), 'internal-link-aliases');
2818
+
2819
+ if (isset($aliases[$to_id]['to'])) {
2820
+ $h_alias_to = su_esc_html($aliases[$to_id]['to']);
2821
+ $text_dest = "/$alias_dir/$h_alias_to/" . '<span class="type">&nbsp;&mdash;&nbsp;';
2822
+
2823
+ if ($this->plugin->module_exists('internal-link-aliases')) {
2824
+ $text_dest .= __('Link Mask', 'seo-ultimate');
2825
+ } else {
2826
+ $text_dest .= __('Link Mask (Disabled)', 'seo-ultimate');
2827
+ $disabled = true;
2828
+ }
2829
+ $text_dest .= '</span>';
2830
+ } else {
2831
+ $text_dest = __('A Deleted Link Mask', 'seo-ultimate');
2832
+ $text_dest = '<span class="type">' . $text_dest . '</span>';
2833
+ $disabled = true;
2834
+ }
2835
+
2836
+ break;
2837
+ }
2838
+
2839
+ $is_url = (('url' == $to_genus) && !$text_dest);
2840
+
2841
+ $to_genus_type = implode('_', array_filter(array($to_genus, $to_type)));
2842
+ $obj = 'obj_' . implode('/', array_filter(array($to_genus_type, $to_id)));
2843
+
2844
+ //URL textbox
2845
+ //(hide if object is selected)
2846
+ $html = "<input name='$name' id='$name' value='";
2847
+ $html .= su_esc_editable_html($is_url ? $to_id : $obj);
2848
+ $html .= "'";
2849
+
2850
+ if ($params) {
2851
+ $e_params = su_esc_attr($params);
2852
+ $html .= " su:params='$e_params'";
2853
+ }
2854
+
2855
+ if ($placeholder) {
2856
+ $e_placeholder = su_esc_attr($placeholder);
2857
+ $html .= " placeholder='$e_placeholder'";
2858
+ }
2859
+
2860
+ $html .= " type='text' class='form-control input-sm textbox regular-text jlsuggest'";
2861
+ $html .= ' title="' . __('Type a URL or start typing the name of an item on your site', 'seo-ultimate') . '"';
2862
+ $html .= $is_url ? '' : ' style="display:none;" ';
2863
+ $html .= ' />';
2864
+
2865
+ //Object box
2866
+ //(hide if URL is entered)
2867
+ $disabled = $disabled ? ' jlsuggest-disabled' : '';
2868
+ $html .= "<div class='jls_text_dest$disabled'";
2869
+ $html .= $is_url ? ' style="display:none;" ' : '';
2870
+ $html .= '>';
2871
+ $html .= '<div class="jls_text_dest_text">';
2872
+ $html .= $text_dest;
2873
+ $html .= '</div>';
2874
+ $html .= '<div><a href="#" onclick="javascript:return false;" class="jls_text_dest_close" title="'.__('Remove this location from this textbox', 'seo-ultimate').'">'.__('X', 'seo-ultimate').'</a></div>';
2875
+ $html .= '</div>';
2876
+
2877
+ return $html;
2878
+ }
2879
+
2880
+ /**
2881
+ * Converts a JLSuggest database string into a URL.
2882
+ *
2883
+ * @since 6.0
2884
+ *
2885
+ * @param string $value The JLSuggest database string to convert.
2886
+ * @param bool $get_src_if_media Whether to get the URL to the actual media item rather than the URL to its WP-powered singular page, if the item is an attachment.
2887
+ * @return string The URL of the referenced destination
2888
+ */
2889
+ function jlsuggest_value_to_url($value, $get_src_if_media=false) {
2890
+
2891
+ list($to_genus, $to_type, $to_id) = $this->jlsuggest_value_explode($value);
2892
+
2893
+ switch ($to_genus) {
2894
+ case 'url':
2895
+ return $to_id; break;
2896
+ case 'posttype':
2897
+ $to_id = (int)$to_id;
2898
+ switch (get_post_status($to_id)) {
2899
+ case 'publish':
2900
+ if ($get_src_if_media && 'attachment' == get_post_type($to_id))
2901
+ return wp_get_attachment_url($to_id);
2902
+
2903
+ return get_permalink($to_id);
2904
+ case false: //Post doesn't exist
2905
+ default: //Post exists but isn't published
2906
+ return false;
2907
+ }
2908
+ break;
2909
+ case 'taxonomy':
2910
+ $to_id = (int)$to_id;
2911
+ $term_link = get_term_link($to_id, $to_type);
2912
+ if ($term_link && !is_wp_error($term_link)) return $term_link;
2913
+ return false;
2914
+ break;
2915
+ case 'home':
2916
+ return suwp::get_blog_home_url(); break;
2917
+ case 'author':
2918
+ $to_id = (int)$to_id;
2919
+ if (is_user_member_of_blog($to_id))
2920
+ return get_author_posts_url($to_id);
2921
+ return false;
2922
+ break;
2923
+ case 'internal-link-alias':
2924
+ if ($this->plugin->module_exists('internal-link-aliases')) {
2925
+ $alias_dir = $this->get_setting('alias_dir', 'go', 'internal-link-aliases');
2926
+ $aliases = $this->get_setting('aliases', array(),'internal-link-aliases');
2927
+
2928
+ if (isset($aliases[$to_id]['to'])) {
2929
+ $u_alias_to = urlencode($aliases[$to_id]['to']);
2930
+ return get_bloginfo('url') . "/$alias_dir/$u_alias_to/";
2931
+ }
2932
+ }
2933
+ return false;
2934
+ break;
2935
+ }
2936
+
2937
+ return false;
2938
+ }
2939
+
2940
+
2941
+ /**
2942
+ * @since 7.6
2943
+ */
2944
+ function should_show_sdf_theme_promo() {
2945
+ return $this->is_sdf_theme_promo_applicable() && $this->get_setting('sdf_theme','', 'settings');
2946
+ }
2947
+
2948
+ /**
2949
+ * @since 7.6
2950
+ */
2951
+ function is_sdf_theme_promo_applicable() {
2952
+ //If the current user can install themes and if SDF isn't already uploaded...
2953
+ if (current_user_can('install_themes') && (wp_get_theme('seodesign')->errors() === false)){
2954
+ $theme = wp_get_theme(); // gets the current theme
2955
+ return ('SEO Design Framework' == $theme->name || 'seodesign' == $theme->template || 'seodesign' == $theme->parent_theme) ? false : true;
2956
+ }
2957
+ else{
2958
+ return true;
2959
+ }
2960
+ }
2961
+
2962
+
2963
+ /**
2964
+ * Display the RSS entries in a list.
2965
+ *
2966
+ * @since 7.6.2
2967
+ *
2968
+ * @param string|array|object $rss RSS url.
2969
+ * @param array $args Widget arguments.
2970
+ */
2971
+ function promo_sdf_banners_rss_output( $rss, $args = array() ) {
2972
+ if ( is_string( $rss ) ) {
2973
+ $rss = fetch_feed($rss);
2974
+ } elseif ( is_array($rss) && isset($rss['url']) ) {
2975
+ $args = $rss;
2976
+ $rss = fetch_feed($rss['url']);
2977
+ } elseif ( !is_object($rss) ) {
2978
+ return;
2979
+ }
2980
+
2981
+ if ( is_wp_error($rss) ) {
2982
+ if ( is_admin() || current_user_can('manage_options') )
2983
+ echo '<p>' . sprintf( __('<strong>RSS Error</strong>: %s'), $rss->get_error_message() ) . '</p>';
2984
+ return;
2985
+ }
2986
+
2987
+ $default_args = array( 'show_author' => 0, 'show_date' => 0, 'show_summary' => 0 );
2988
+ $args = wp_parse_args( $args, $default_args );
2989
+ extract( $args, EXTR_SKIP );
2990
+
2991
+ $items = (int) $items;
2992
+ if ( $items < 1 || 20 < $items )
2993
+ $items = 10;
2994
+ $show_summary = (int) $show_summary;
2995
+ $show_author = (int) $show_author;
2996
+ $show_date = (int) $show_date;
2997
+
2998
+ if ( !$rss->get_item_quantity() ) {
2999
+ echo '<ul><li>' . __( 'An error has occurred, which probably means the feed is down. Try again later.' ) . '</li></ul>';
3000
+ $rss->__destruct();
3001
+ unset($rss);
3002
+ return;
3003
+ }
3004
+
3005
+ foreach ( $rss->get_items(0, $items) as $item ) {
3006
+ $link = $item->get_link();
3007
+ while ( stristr($link, 'http') != $link )
3008
+ $link = substr($link, 1);
3009
+ $link = esc_url(strip_tags($link));
3010
+ $title = esc_attr(strip_tags($item->get_title()));
3011
+ if ( empty($title) )
3012
+ $title = '';
3013
+
3014
+ $desc = str_replace( array("\n", "\r"), ' ', esc_attr( strip_tags( @html_entity_decode( $item->get_description(), ENT_QUOTES, get_option('blog_charset') ) ) ) );
3015
+ $excerpt = wp_html_excerpt( $desc, 120 );
3016
+
3017
+ // Append ellipsis. Change existing [...] to [&hellip;].
3018
+ if ( '[...]' == substr( $excerpt, -5 ) )
3019
+ $excerpt = substr( $excerpt, 0, -5 ) . '[&hellip;]';
3020
+ elseif ( '[&hellip;]' != substr( $excerpt, -10 ) && $desc != $excerpt )
3021
+ $excerpt .= ' [&hellip;]';
3022
+
3023
+ $excerpt = esc_html( $excerpt );
3024
+
3025
+ if ( $show_summary ) {
3026
+ $summary = "<p>$excerpt</p>";
3027
+ } else {
3028
+ $summary = '';
3029
+ }
3030
+
3031
+ $date = '';
3032
+ if ( $show_date ) {
3033
+ $date = $item->get_date( 'U' );
3034
+
3035
+ if ( $date ) {
3036
+ $date = ' <span class="rss-date">' . date_i18n( get_option( 'date_format' ), $date ) . '</span>';
3037
+ }
3038
+ }
3039
+
3040
+ $author = '';
3041
+ if ( $show_author ) {
3042
+ $author = $item->get_author();
3043
+ if ( is_object($author) ) {
3044
+ $author = $author->get_name();
3045
+ $author = ' <cite>' . esc_html( strip_tags( $author ) ) . '</cite>';
3046
+ }
3047
+ }
3048
+
3049
+ if ( $link == '' ) {
3050
+ echo "<h3>$title</h3>{$summary}";
3051
+ } else {
3052
+ echo "<h3>$title</h3>{$summary}<p><a class='btn btn-large btn-warning' href='$link' target='_blank' rel='nofollow'>Read More</a></p>";
3053
+ }
3054
+ }
3055
+ $rss->__destruct();
3056
+ unset($rss);
3057
+ }
3058
+
3059
+ /**
3060
+ * @since 7.6.2
3061
+ */
3062
+ function promo_sdf_banners() {
3063
+
3064
+ if ($this->should_show_sdf_theme_promo()) {
3065
+ ?>
3066
+ <div id="sds_promo_blog_post" class="hide">
3067
+ <?php $this->promo_sdf_banners_rss_output( 'http://feeds.seodesignsolutions.com/SeoDesignSolutionsBlog', array('show_summary' => 1, 'show_date' => 0, 'items' => 1) ); ?>
3068
+ </div>
3069
+ <div id="sdf-promo-carousel"></div>
3070
+ <p>Remove these ads?<br />
3071
+ <a href="https://seoultimateplus.com/?ref=su-rmv-ad" target="_blank" title="Upgrade to SEO Ultimate+">Upgrade to SEO Ultimate+</a></p>
3072
+ <?php
3073
+ }
3074
+ }
3075
+ }
3076
  ?>
modules/opengraph/opengraph.php CHANGED
@@ -68,6 +68,7 @@ class SU_OpenGraph extends SU_Module {
68
  return array(
69
  'og' => 'http://ogp.me/ns#'
70
  , 'fb' => 'http://ogp.me/ns/fb#'
 
71
  );
72
  }
73
 
68
  return array(
69
  'og' => 'http://ogp.me/ns#'
70
  , 'fb' => 'http://ogp.me/ns/fb#'
71
+ , 'article' => 'http://ogp.me/ns/article#'
72
  );
73
  }
74
 
modules/sdf-ads/banners/InternalLinkBanner.jpg DELETED
Binary file
modules/sdf-ads/banners/MetaWritingBanner.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-1.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-2.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-3.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-4.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-5.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-Ultimate-Dashboard-Bannner-6.jpg DELETED
Binary file
modules/sdf-ads/banners/SEO-VideoTraining-Banner-v3.jpg DELETED
Binary file
modules/sdf-ads/banners/sdf-website-silo-architecture.png ADDED
Binary file
modules/sdf-ads/banners/seo-design-framework-banner.jpg ADDED
Binary file
modules/sdf-ads/banners/seo-ultimate-plugin-done-for-you-service.jpg ADDED
Binary file
modules/sdf-ads/banners/seo-ultimate-plus-video-training.jpg ADDED
Binary file
modules/sdf-ads/banners/seo-ultimate-wordpress-dashboard.png ADDED
Binary file
modules/sdf-ads/sdf-ads.css CHANGED
@@ -26,7 +26,7 @@
26
 
27
  /* Declare heights because of positioning of img element */
28
  #sdf-promo-carousel .carousel .item {
29
- height: 330px;
30
  background-color: #868686;
31
  }
32
  #sdf-promo-carousel .carousel-inner > .item a img {
26
 
27
  /* Declare heights because of positioning of img element */
28
  #sdf-promo-carousel .carousel .item {
29
+ height: 350px;
30
  background-color: #868686;
31
  }
32
  #sdf-promo-carousel .carousel-inner > .item a img {
modules/sdf-ads/sdf-ads.js CHANGED
@@ -8,23 +8,18 @@ jQuery(document).ready(function($) {
8
  var sds_promo_blog_post = $('#sds_promo_blog_post').html();
9
  var banners_remote = ({
10
  "banners": [
11
- {"banner_img":"SEO-Ultimate-Dashboard-Bannner-1.jpg", "banner_link":"https://seoultimateplus.com/?ref=su-sb1"},
12
- {"banner_img":"SEO-Ultimate-Dashboard-Bannner-2.jpg", "banner_link":"https://seoultimateplus.com/?ref=su-sb2"},
13
- {"banner_img":"SEO-Ultimate-Dashboard-Bannner-3.jpg", "banner_link":"https://seoultimateplus.com/?ref=su-sb3"},
14
- {"banner_img":"SEO-Ultimate-Dashboard-Bannner-4.jpg", "banner_link":"https://seoultimateplus.com/?ref=su-sb4"},
15
- {"banner_img":"SEO-Ultimate-Dashboard-Bannner-5.jpg", "banner_link":"https://seoultimateplus.com/?ref=su-sb5"},
16
- {"banner_img":"SEO-Ultimate-Dashboard-Bannner-6.jpg", "banner_link":"https://seoultimateplus.com/?ref=su-sb6"},
17
- {"banner_img":"InternalLinkBanner.jpg", "banner_link":"https://seodesignframework.leadpages.net/internal-links/"},
18
- {"banner_img":"MetaWritingBanner.jpg", "banner_link":"https://seodesignframework.leadpages.net/meta-titles-descriptions/"}
19
  ],
20
  "slides": [
21
  {"slide_cap":"<h3>Download Jeffrey’s Brain</h3><p>Get Equipped for Success - Tips from Our Founder. Download: 20 SEO Tips, SEO for Large Websites and the Organic SEO EBook today.</p>", "slide_link":"http://www.seodesignframework.com/ebooks/"},
22
- {"slide_cap":"<h3>Got Design?</h3><p>Unleash Your Best Design Concepts with Drag-n-Drop Controls that Give You the Power to Implement Complex Designs Quickly and Easily</p>", "slide_link":"http://www.seodesignframework.com/sdf-drag-and-drop-page-builder/"},
23
- {"slide_cap":"<h3>Silos Made Easy</h3><p>Deploy Perfect Website Silo Architecture Quickly and Easily with the SEO Design Framework.</p>", "slide_link":"http://www.seodesignframework.com/website-silo-architecture/"},
24
- {"slide_cap":"<h3>What, No Control?</h3><p>Become Master of your Blog with Page-Level Controls that Liberate Designs and Crush Limitations of other Themes and Frameworks.</p>", "slide_link":"http://www.seodesignframework.com/page-level-controls/"}
25
  ],
26
  "dashboard_widget": [
27
- {"title":"Learn How to Use SEO Ultimate", "content":"<p>Get access to <a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate video training\" href=\"https://seodesignframework.leadpages.net/seo-ultimate-video-training/\">detailed video training</a> covering each module.</p><a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate video training\" href=\"https://seodesignframework.leadpages.net/seo-ultimate-video-training/\"><img src=\"" + suModulesSdfAdsSdfAdsL10n.sdf_banners_url + "SEO-VideoTraining-Banner-v3.jpg\" alt=\"SEO Ultimate video training\" /></a>"}
28
  ]
29
  })
30
 
8
  var sds_promo_blog_post = $('#sds_promo_blog_post').html();
9
  var banners_remote = ({
10
  "banners": [
11
+ {"banner_img":"seo-design-framework-banner.jpg", "banner_link":"http://www.seodesignframework.com/"},
12
+ {"banner_img":"sdf-website-silo-architecture.png", "banner_link":"http://www.seodesignframework.com/website-silo-architecture/"},
13
+ {"banner_img":"seo-ultimate-plugin-done-for-you-service.jpg", "banner_link":"http://go.seoultimateplus.com/done-for-you"},
14
+ {"banner_img":"seo-ultimate-plus-video-training.jpg", "banner_link":"https://seodesignframework.leadpages.co/seo-ultimate-video-training/"},
15
+ {"banner_img":"seo-ultimate-wordpress-dashboard.png", "banner_link":"http://go.seoultimateplus.com/get-help"}
 
 
 
16
  ],
17
  "slides": [
18
  {"slide_cap":"<h3>Download Jeffrey’s Brain</h3><p>Get Equipped for Success - Tips from Our Founder. Download: 20 SEO Tips, SEO for Large Websites and the Organic SEO EBook today.</p>", "slide_link":"http://www.seodesignframework.com/ebooks/"},
19
+ {"slide_cap":"<h3>Silos Made Easy</h3><p>Deploy Perfect Website Silo Architecture Quickly and Easily with the SEO Design Framework.</p>", "slide_link":"http://www.seodesignframework.com/website-silo-architecture/"}
 
 
20
  ],
21
  "dashboard_widget": [
22
+ {"title":"Supercharge your SEO", "content":"<p>Get access to <a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate video training\" href=\"http://go.seoultimateplus.com/get-help/\">detailed video training</a> and more.</p><a rel=\"nofollow\" target=\"_blank\" title=\"SEO Ultimate video training\" href=\"http://go.seoultimateplus.com/get-help/\"><img src=\"" + suModulesSdfAdsSdfAdsL10n.sdf_banners_url + "seo-ultimate-wordpress-dashboard.png\" alt=\"SEO Ultimate video training\" /></a>"}
23
  ]
24
  })
25
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: SEO Design Solutions, JohnLamansky, djalexandar, M Rub Shuvo
3
  Tags: seo, SEO Ultimate, suite, google, yahoo, bing, search engines, admin, post, page, custom post types, categories, tags, terms, custom taxonomies, base, title, title tag, wp_title, meta, robots, noindex, nofollow, canonical, HTTP headers, 404, robots.txt, htaccess, slugs, url, anchor, more, link, excerpt, permalink, links, autolinks, code, footer, settings, redirect, 301, 302, 307, modules, uninstallable, reinstallable, downgradable, import, export, CSV, affiliate, Open Graph, og, microdata, Facebook, Twitter, Schema.org
4
  Requires at least: 3.9
5
- Tested up to: 4.2.2
6
- Stable tag: 7.6.5.6
7
 
8
  This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
9
 
@@ -254,6 +254,11 @@ Frequently asked questions, settings help, and troubleshooting tips for SEO Ulti
254
 
255
  == Changelog ==
256
 
 
 
 
 
 
257
  = Version 7.6.5.7 (June 29, 2015) =
258
  * Improvement: SEO Admin Toolbar Menu
259
  * Bugfix: Bootstrap/Prototype Conflict Fix
2
  Contributors: SEO Design Solutions, JohnLamansky, djalexandar, M Rub Shuvo
3
  Tags: seo, SEO Ultimate, suite, google, yahoo, bing, search engines, admin, post, page, custom post types, categories, tags, terms, custom taxonomies, base, title, title tag, wp_title, meta, robots, noindex, nofollow, canonical, HTTP headers, 404, robots.txt, htaccess, slugs, url, anchor, more, link, excerpt, permalink, links, autolinks, code, footer, settings, redirect, 301, 302, 307, modules, uninstallable, reinstallable, downgradable, import, export, CSV, affiliate, Open Graph, og, microdata, Facebook, Twitter, Schema.org
4
  Requires at least: 3.9
5
+ Tested up to: 4.3.1
6
+ Stable tag: 7.6.5.8
7
 
8
  This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
9
 
254
 
255
  == Changelog ==
256
 
257
+ = Version 7.6.5.8 (September 23, 2015) =
258
+ * Bugfix: Admin pagination
259
+ * Bugfix: Problem Of Wrong ID's
260
+ * Bugfix: Yandex Validation Error For Open Graph Article Prefix
261
+
262
  = Version 7.6.5.7 (June 29, 2015) =
263
  * Improvement: SEO Admin Toolbar Menu
264
  * Bugfix: Bootstrap/Prototype Conflict Fix
seo-ultimate.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: SEO Ultimate
4
  Plugin URI: http://www.seodesignsolutions.com/wordpress-seo/
5
  Description: This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
6
- Version: 7.6.5.7
7
  Author: SEO Design Solutions
8
  Author URI: http://www.seodesignsolutions.com/
9
  Text Domain: seo-ultimate
@@ -12,7 +12,7 @@ Text Domain: seo-ultimate
12
  /**
13
  * The main SEO Ultimate plugin file.
14
  * @package SeoUltimate
15
- * @version 7.6.5.7
16
  * @link http://www.seodesignsolutions.com/wordpress-seo/ SEO Ultimate Homepage
17
  */
18
 
@@ -48,10 +48,10 @@ define('SU_MINIMUM_WP_VER', '3.9');
48
  //Reading plugin info from constants is faster than trying to parse it from the header above.
49
  define('SU_PLUGIN_NAME', 'SEO Ultimate');
50
  define('SU_PLUGIN_URI', 'http://www.seodesignsolutions.com/wordpress-seo/');
51
- define('SU_VERSION', '7.6.5.7');
52
  define('SU_AUTHOR', 'SEO Design Solutions');
53
  define('SU_AUTHOR_URI', 'http://www.seodesignframework.com/');
54
- define('SU_USER_AGENT', 'SeoUltimate/7.6.5.7');
55
 
56
  /********** INCLUDES **********/
57
 
3
  Plugin Name: SEO Ultimate
4
  Plugin URI: http://www.seodesignsolutions.com/wordpress-seo/
5
  Description: This all-in-one SEO plugin gives you control over meta titles & descriptions, open graph, auto-linking, rich-snippets, 404 monitoring, siloing & more.
6
+ Version: 7.6.5.8
7
  Author: SEO Design Solutions
8
  Author URI: http://www.seodesignsolutions.com/
9
  Text Domain: seo-ultimate
12
  /**
13
  * The main SEO Ultimate plugin file.
14
  * @package SeoUltimate
15
+ * @version 7.6.5.8
16
  * @link http://www.seodesignsolutions.com/wordpress-seo/ SEO Ultimate Homepage
17
  */
18
 
48
  //Reading plugin info from constants is faster than trying to parse it from the header above.
49
  define('SU_PLUGIN_NAME', 'SEO Ultimate');
50
  define('SU_PLUGIN_URI', 'http://www.seodesignsolutions.com/wordpress-seo/');
51
+ define('SU_VERSION', '7.6.5.8');
52
  define('SU_AUTHOR', 'SEO Design Solutions');
53
  define('SU_AUTHOR_URI', 'http://www.seodesignframework.com/');
54
+ define('SU_USER_AGENT', 'SeoUltimate/7.6.5.8');
55
 
56
  /********** INCLUDES **********/
57
 
translations/seo-ultimate-en_US.mo CHANGED
Binary file
translations/seo-ultimate-en_US.po CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: SEO Ultimate v7.6.5.7\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
- "POT-Creation-Date: 2015-06-29 20:58+0100\n"
8
- "PO-Revision-Date: 2015-06-29 20:58+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
@@ -56,7 +56,7 @@ msgstr ""
56
  msgid "Log"
57
  msgstr ""
58
 
59
- #: modules/404s/fofs-log.php:118 modules/class.su-module.php:1163
60
  msgid "Actions"
61
  msgstr ""
62
 
@@ -149,7 +149,7 @@ msgstr ""
149
 
150
  #: modules/404s/fofs-settings.php:17
151
  #: modules/internal-link-aliases/internal-link-aliases.php:43
152
- #: modules/opengraph/opengraph.php:351 modules/titles/titles.php:41
153
  msgid "Settings"
154
  msgstr ""
155
 
@@ -203,7 +203,7 @@ msgstr ""
203
  #: modules/meta/meta-keywords.php:178 modules/meta/meta-robots.php:52
204
  #: modules/meta/webmaster-verify.php:95 modules/meta/webmaster-verify.php:101
205
  #: modules/more-links/more-links.php:104 modules/more-links/more-links.php:111
206
- #: modules/opengraph/opengraph.php:545
207
  #: modules/rich-snippets/rich-snippets.php:410
208
  #: modules/rich-snippets/rich-snippets.php:417
209
  #: modules/settings/settings.php:63
@@ -1172,98 +1172,98 @@ msgstr ""
1172
  msgid "&raquo;"
1173
  msgstr ""
1174
 
1175
- #: modules/class.su-module.php:1150
1176
  #, php-format
1177
  msgid "Displaying %s&#8211;%s of %s"
1178
  msgstr ""
1179
 
1180
- #: modules/class.su-module.php:1164
1181
  msgid "ID"
1182
  msgstr ""
1183
 
1184
- #: modules/class.su-module.php:1217
1185
  msgid "View"
1186
  msgstr ""
1187
 
1188
- #: modules/class.su-module.php:1219
1189
  msgid "Edit"
1190
  msgstr ""
1191
 
1192
- #: modules/class.su-module.php:1389
1193
  msgid "Settings updated."
1194
  msgstr ""
1195
 
1196
- #: modules/class.su-module.php:1410
1197
  msgid "Save Changes"
1198
  msgstr ""
1199
 
1200
- #: modules/class.su-module.php:1897
1201
  msgid ""
1202
  "Are you sure you want to replace the textbox contents with this default "
1203
  "value?"
1204
  msgstr ""
1205
 
1206
- #: modules/class.su-module.php:1926 modules/settings/settings-data.php:23
1207
  msgid "Reset"
1208
  msgstr ""
1209
 
1210
- #: modules/class.su-module.php:2778 modules/class.su-module.php:2790
1211
  #, php-format
1212
  msgid "A Deleted %s"
1213
  msgstr ""
1214
 
1215
- #: modules/class.su-module.php:2780
1216
  msgid "A Deleted Post"
1217
  msgstr ""
1218
 
1219
- #: modules/class.su-module.php:2795
1220
  msgid "A Deleted Term"
1221
  msgstr ""
1222
 
1223
- #: modules/class.su-module.php:2801 modules/meta/meta-descriptions.php:31
1224
- #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:352
1225
  #: plugin/class.seo-ultimate.php:1876
1226
  msgid "Blog Homepage"
1227
  msgstr ""
1228
 
1229
- #: modules/class.su-module.php:2806 plugin/class.seo-ultimate.php:1952
1230
  msgid "Author"
1231
  msgstr ""
1232
 
1233
- #: modules/class.su-module.php:2808
1234
  msgid "A Deleted User"
1235
  msgstr ""
1236
 
1237
- #: modules/class.su-module.php:2823 plugin/class.seo-ultimate.php:1982
1238
  msgid "Link Mask"
1239
  msgstr ""
1240
 
1241
- #: modules/class.su-module.php:2825
1242
  msgid "Link Mask (Disabled)"
1243
  msgstr ""
1244
 
1245
- #: modules/class.su-module.php:2830
1246
  msgid "A Deleted Link Mask"
1247
  msgstr ""
1248
 
1249
- #: modules/class.su-module.php:2860
1250
  msgid "Type a URL or start typing the name of an item on your site"
1251
  msgstr ""
1252
 
1253
- #: modules/class.su-module.php:2873
1254
  msgid "Remove this location from this textbox"
1255
  msgstr ""
1256
 
1257
- #: modules/class.su-module.php:2873
1258
  msgid "X"
1259
  msgstr ""
1260
 
1261
- #: modules/class.su-module.php:2982 modules/sds-blog/sds-blog.php:138
1262
  #, php-format
1263
  msgid "<strong>RSS Error</strong>: %s"
1264
  msgstr ""
1265
 
1266
- #: modules/class.su-module.php:2998 modules/sds-blog/sds-blog.php:154
1267
  msgid ""
1268
  "An error has occurred, which probably means the feed is down. Try again "
1269
  "later."
@@ -1898,12 +1898,12 @@ msgid "Meta Keywords"
1898
  msgstr ""
1899
 
1900
  #: modules/meta/meta-keywords.php:38 modules/meta/meta-robots.php:22
1901
- #: modules/opengraph/opengraph.php:349
1902
  msgid "Sitewide Values"
1903
  msgstr ""
1904
 
1905
  #: modules/meta/meta-keywords.php:39 modules/noindex/noindex.php:50
1906
- #: modules/opengraph/opengraph.php:350
1907
  msgid "Default Values"
1908
  msgstr ""
1909
 
@@ -2368,8 +2368,8 @@ msgid "Noindex"
2368
  msgstr ""
2369
 
2370
  #: modules/noindex/noindex.php:69 modules/noindex/noindex.php:80
2371
- #: modules/opengraph/opengraph.php:320 modules/opengraph/opengraph.php:451
2372
- #: modules/opengraph/opengraph.php:452
2373
  msgid "Use default"
2374
  msgstr ""
2375
 
@@ -2460,348 +2460,348 @@ msgstr ""
2460
  msgid "Open Graph"
2461
  msgstr ""
2462
 
2463
- #: modules/opengraph/opengraph.php:322
2464
  msgid "Type"
2465
  msgstr ""
2466
 
2467
- #: modules/opengraph/opengraph.php:327
2468
  msgid "Title"
2469
  msgstr ""
2470
 
2471
- #: modules/opengraph/opengraph.php:332
2472
  msgid "Description"
2473
  msgstr ""
2474
 
2475
- #: modules/opengraph/opengraph.php:337
2476
  msgid "Image"
2477
  msgstr ""
2478
 
2479
- #: modules/opengraph/opengraph.php:360
2480
  msgid "Site Name"
2481
  msgstr ""
2482
 
2483
- #: modules/opengraph/opengraph.php:361
2484
  msgid "Facebook App ID"
2485
  msgstr ""
2486
 
2487
- #: modules/opengraph/opengraph.php:362
2488
  msgid "@username of website"
2489
  msgstr ""
2490
 
2491
- #: modules/opengraph/opengraph.php:363
2492
  msgid "Same as twitter:site, but the user&#8217;s Twitter ID"
2493
  msgstr ""
2494
 
2495
- #: modules/opengraph/opengraph.php:364
2496
  msgid "@username of content creator"
2497
  msgstr ""
2498
 
2499
- #: modules/opengraph/opengraph.php:365
2500
  msgid "Twitter user ID of content creator"
2501
  msgstr ""
2502
 
2503
- #: modules/opengraph/opengraph.php:366
2504
  msgid "Description of content (maximum 200 characters)"
2505
  msgstr ""
2506
 
2507
- #: modules/opengraph/opengraph.php:367
2508
  msgid "Title of content (maximum 70 characters)"
2509
  msgstr ""
2510
 
2511
- #: modules/opengraph/opengraph.php:368
2512
  msgid "URL of image to use in the card. Image must be less than 1MB in size."
2513
  msgstr ""
2514
 
2515
- #: modules/opengraph/opengraph.php:369
2516
  msgid "Width of image in pixels"
2517
  msgstr ""
2518
 
2519
- #: modules/opengraph/opengraph.php:370
2520
  msgid "Height of image in pixels"
2521
  msgstr ""
2522
 
2523
- #: modules/opengraph/opengraph.php:371
2524
  msgid ""
2525
  "Top customizable data field, can be a relatively short string (ie \"$3.99\")"
2526
  msgstr ""
2527
 
2528
- #: modules/opengraph/opengraph.php:372 modules/opengraph/opengraph.php:374
2529
  msgid ""
2530
  "Customizable label or units for the information in twitter:data1 (best "
2531
  "practice: use all caps)"
2532
  msgstr ""
2533
 
2534
- #: modules/opengraph/opengraph.php:373
2535
  msgid ""
2536
  "Bottom customizable data field, can be a relatively short string (ie "
2537
  "\"Seattle, WA\")"
2538
  msgstr ""
2539
 
2540
- #: modules/opengraph/opengraph.php:375
2541
  msgid "1st image in the gallery. Images must be less than 1MB in size."
2542
  msgstr ""
2543
 
2544
- #: modules/opengraph/opengraph.php:376
2545
  msgid "2nd image in the gallery. Images must be less than 1MB in size."
2546
  msgstr ""
2547
 
2548
- #: modules/opengraph/opengraph.php:377
2549
  msgid "3rd image in the gallery. Images must be less than 1MB in size."
2550
  msgstr ""
2551
 
2552
- #: modules/opengraph/opengraph.php:378
2553
  msgid "4th image in the gallery. Images must be less than 1MB in size."
2554
  msgstr ""
2555
 
2556
- #: modules/opengraph/opengraph.php:379
2557
  msgid " \tHTTPS URL of player iframe"
2558
  msgstr ""
2559
 
2560
- #: modules/opengraph/opengraph.php:380
2561
  msgid "Width of iframe in pixels"
2562
  msgstr ""
2563
 
2564
- #: modules/opengraph/opengraph.php:381
2565
  msgid "Height of iframe in pixels"
2566
  msgstr ""
2567
 
2568
- #: modules/opengraph/opengraph.php:382
2569
  msgid "URL to raw video or audio stream"
2570
  msgstr ""
2571
 
2572
- #: modules/opengraph/opengraph.php:383
2573
  msgid "Name of your iPhone app"
2574
  msgstr ""
2575
 
2576
- #: modules/opengraph/opengraph.php:384
2577
  msgid "Your app ID in the iTunes App Store (Note: NOT your bundle ID)"
2578
  msgstr ""
2579
 
2580
- #: modules/opengraph/opengraph.php:385
2581
  msgid ""
2582
  "Your app&#8217;s custom URL scheme (you must include \"://\" after your "
2583
  "scheme name)"
2584
  msgstr ""
2585
 
2586
- #: modules/opengraph/opengraph.php:386
2587
  msgid "Name of your iPad optimized app"
2588
  msgstr ""
2589
 
2590
- #: modules/opengraph/opengraph.php:387
2591
  msgid "Your app ID in the iTunes App Store"
2592
  msgstr ""
2593
 
2594
- #: modules/opengraph/opengraph.php:388
2595
  msgid "Your app&#8217;s custom URL scheme"
2596
  msgstr ""
2597
 
2598
- #: modules/opengraph/opengraph.php:389
2599
  msgid "Name of your Android app"
2600
  msgstr ""
2601
 
2602
- #: modules/opengraph/opengraph.php:390
2603
  msgid "Your app ID in the Google Play Store"
2604
  msgstr ""
2605
 
2606
- #: modules/opengraph/opengraph.php:391
2607
  msgid "Your app#8217;s custom URL scheme"
2608
  msgstr ""
2609
 
2610
- #: modules/opengraph/opengraph.php:398
2611
  msgid "Default Types"
2612
  msgstr ""
2613
 
2614
- #: modules/opengraph/opengraph.php:400
2615
  msgid "Post Type"
2616
  msgstr ""
2617
 
2618
- #: modules/opengraph/opengraph.php:401
2619
  msgid "Open Graph Type"
2620
  msgstr ""
2621
 
2622
- #: modules/opengraph/opengraph.php:402
2623
  msgid "Twitter Type"
2624
  msgstr ""
2625
 
2626
- #: modules/opengraph/opengraph.php:417 modules/opengraph/opengraph.php:422
2627
  msgid "Default Image"
2628
  msgstr ""
2629
 
2630
- #: modules/opengraph/opengraph.php:420
2631
  msgid ""
2632
  "In the box below, you can specify an image URL or an image from your media "
2633
  "library to use as a default image in the event that there is no image "
2634
  "otherwise specified for a given webpage on your site."
2635
  msgstr ""
2636
 
2637
- #: modules/opengraph/opengraph.php:429
2638
  msgid "Include author data for posts"
2639
  msgstr ""
2640
 
2641
- #: modules/opengraph/opengraph.php:429
2642
  msgid "Open Graph Data"
2643
  msgstr ""
2644
 
2645
- #: modules/opengraph/opengraph.php:431
2646
  msgid "Use the non-validating code prescribed by Open Graph and Twitter"
2647
  msgstr ""
2648
 
2649
- #: modules/opengraph/opengraph.php:432
2650
  msgid "Alter the code to validate as XHTML"
2651
  msgstr ""
2652
 
2653
- #: modules/opengraph/opengraph.php:433
2654
  msgid "Alter the code to validate as HTML5"
2655
  msgstr ""
2656
 
2657
- #: modules/opengraph/opengraph.php:434
2658
  msgid "HTML Validation"
2659
  msgstr ""
2660
 
2661
- #: modules/opengraph/opengraph.php:440 modules/titles/titles.php:91
2662
  msgid "Blog Homepage Title"
2663
  msgstr ""
2664
 
2665
- #: modules/opengraph/opengraph.php:441
2666
  msgid "Blog Homepage Description"
2667
  msgstr ""
2668
 
2669
- #: modules/opengraph/opengraph.php:442
2670
  msgid "Blog Homepage Image"
2671
  msgstr ""
2672
 
2673
- #: modules/opengraph/opengraph.php:448 modules/widgets/widgets.php:140
2674
  msgid "Title:"
2675
  msgstr ""
2676
 
2677
- #: modules/opengraph/opengraph.php:449
2678
  msgid "Description:"
2679
  msgstr ""
2680
 
2681
- #: modules/opengraph/opengraph.php:450
2682
  msgid "Image:"
2683
  msgstr ""
2684
 
2685
- #: modules/opengraph/opengraph.php:451
2686
  msgid "Open Graph Type:"
2687
  msgstr ""
2688
 
2689
- #: modules/opengraph/opengraph.php:452
2690
  msgid "Twitter Type:"
2691
  msgstr ""
2692
 
2693
- #: modules/opengraph/opengraph.php:477
2694
  #, php-format
2695
  msgid "Featured Image: %s"
2696
  msgstr ""
2697
 
2698
- #: modules/opengraph/opengraph.php:485
2699
  #: modules/rich-snippets/rich-snippets.php:357
2700
  msgid "None"
2701
  msgstr ""
2702
 
2703
- #: modules/opengraph/opengraph.php:486
2704
  msgid "Internet"
2705
  msgstr ""
2706
 
2707
- #: modules/opengraph/opengraph.php:487
2708
  msgid "Article"
2709
  msgstr ""
2710
 
2711
- #: modules/opengraph/opengraph.php:488
2712
  msgid "Blog"
2713
  msgstr ""
2714
 
2715
- #: modules/opengraph/opengraph.php:489
2716
  msgid "Profile"
2717
  msgstr ""
2718
 
2719
- #: modules/opengraph/opengraph.php:490
2720
  msgid "Website"
2721
  msgstr ""
2722
 
2723
- #: modules/opengraph/opengraph.php:491
2724
  msgid "Products"
2725
  msgstr ""
2726
 
2727
- #: modules/opengraph/opengraph.php:492
2728
  msgid "Book"
2729
  msgstr ""
2730
 
2731
- #: modules/opengraph/opengraph.php:493
2732
  msgid "Music"
2733
  msgstr ""
2734
 
2735
- #: modules/opengraph/opengraph.php:494
2736
  msgid "Album"
2737
  msgstr ""
2738
 
2739
- #: modules/opengraph/opengraph.php:495
2740
  msgid "Playlist"
2741
  msgstr ""
2742
 
2743
- #: modules/opengraph/opengraph.php:496
2744
  msgid "Radio Station"
2745
  msgstr ""
2746
 
2747
- #: modules/opengraph/opengraph.php:497
2748
  msgid "Song"
2749
  msgstr ""
2750
 
2751
- #: modules/opengraph/opengraph.php:498
2752
  msgid "Videos"
2753
  msgstr ""
2754
 
2755
- #: modules/opengraph/opengraph.php:499
2756
  msgid "Movie"
2757
  msgstr ""
2758
 
2759
- #: modules/opengraph/opengraph.php:500
2760
  msgid "TV Episode"
2761
  msgstr ""
2762
 
2763
- #: modules/opengraph/opengraph.php:501
2764
  msgid "TV Show"
2765
  msgstr ""
2766
 
2767
- #: modules/opengraph/opengraph.php:502
2768
  msgid "Video"
2769
  msgstr ""
2770
 
2771
- #: modules/opengraph/opengraph.php:509
2772
  msgid "Summary"
2773
  msgstr ""
2774
 
2775
- #: modules/opengraph/opengraph.php:510
2776
  msgid "Product"
2777
  msgstr ""
2778
 
2779
- #: modules/opengraph/opengraph.php:511
2780
  #: modules/rich-snippets/rich-snippets.php:120
2781
  msgid "Photo"
2782
  msgstr ""
2783
 
2784
- #: modules/opengraph/opengraph.php:512
2785
  msgid "Summary Large Image"
2786
  msgstr ""
2787
 
2788
- #: modules/opengraph/opengraph.php:513
2789
  msgid "Gallery"
2790
  msgstr ""
2791
 
2792
- #: modules/opengraph/opengraph.php:514
2793
  msgid "Player"
2794
  msgstr ""
2795
 
2796
- #: modules/opengraph/opengraph.php:515
2797
  msgid "App"
2798
  msgstr ""
2799
 
2800
- #: modules/opengraph/opengraph.php:537
2801
  msgid "Twitter Handle"
2802
  msgstr ""
2803
 
2804
- #: modules/opengraph/opengraph.php:546
2805
  msgid ""
2806
  "\n"
2807
  "<ul>\n"
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: SEO Ultimate v7.6.5.8\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
+ "POT-Creation-Date: 2015-09-24 02:09+0100\n"
8
+ "PO-Revision-Date: 2015-09-24 02:09+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
56
  msgid "Log"
57
  msgstr ""
58
 
59
+ #: modules/404s/fofs-log.php:118 modules/class.su-module.php:1164
60
  msgid "Actions"
61
  msgstr ""
62
 
149
 
150
  #: modules/404s/fofs-settings.php:17
151
  #: modules/internal-link-aliases/internal-link-aliases.php:43
152
+ #: modules/opengraph/opengraph.php:352 modules/titles/titles.php:41
153
  msgid "Settings"
154
  msgstr ""
155
 
203
  #: modules/meta/meta-keywords.php:178 modules/meta/meta-robots.php:52
204
  #: modules/meta/webmaster-verify.php:95 modules/meta/webmaster-verify.php:101
205
  #: modules/more-links/more-links.php:104 modules/more-links/more-links.php:111
206
+ #: modules/opengraph/opengraph.php:546
207
  #: modules/rich-snippets/rich-snippets.php:410
208
  #: modules/rich-snippets/rich-snippets.php:417
209
  #: modules/settings/settings.php:63
1172
  msgid "&raquo;"
1173
  msgstr ""
1174
 
1175
+ #: modules/class.su-module.php:1151
1176
  #, php-format
1177
  msgid "Displaying %s&#8211;%s of %s"
1178
  msgstr ""
1179
 
1180
+ #: modules/class.su-module.php:1165
1181
  msgid "ID"
1182
  msgstr ""
1183
 
1184
+ #: modules/class.su-module.php:1218
1185
  msgid "View"
1186
  msgstr ""
1187
 
1188
+ #: modules/class.su-module.php:1220
1189
  msgid "Edit"
1190
  msgstr ""
1191
 
1192
+ #: modules/class.su-module.php:1390
1193
  msgid "Settings updated."
1194
  msgstr ""
1195
 
1196
+ #: modules/class.su-module.php:1411
1197
  msgid "Save Changes"
1198
  msgstr ""
1199
 
1200
+ #: modules/class.su-module.php:1898
1201
  msgid ""
1202
  "Are you sure you want to replace the textbox contents with this default "
1203
  "value?"
1204
  msgstr ""
1205
 
1206
+ #: modules/class.su-module.php:1927 modules/settings/settings-data.php:23
1207
  msgid "Reset"
1208
  msgstr ""
1209
 
1210
+ #: modules/class.su-module.php:2779 modules/class.su-module.php:2791
1211
  #, php-format
1212
  msgid "A Deleted %s"
1213
  msgstr ""
1214
 
1215
+ #: modules/class.su-module.php:2781
1216
  msgid "A Deleted Post"
1217
  msgstr ""
1218
 
1219
+ #: modules/class.su-module.php:2796
1220
  msgid "A Deleted Term"
1221
  msgstr ""
1222
 
1223
+ #: modules/class.su-module.php:2802 modules/meta/meta-descriptions.php:31
1224
+ #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:353
1225
  #: plugin/class.seo-ultimate.php:1876
1226
  msgid "Blog Homepage"
1227
  msgstr ""
1228
 
1229
+ #: modules/class.su-module.php:2807 plugin/class.seo-ultimate.php:1952
1230
  msgid "Author"
1231
  msgstr ""
1232
 
1233
+ #: modules/class.su-module.php:2809
1234
  msgid "A Deleted User"
1235
  msgstr ""
1236
 
1237
+ #: modules/class.su-module.php:2824 plugin/class.seo-ultimate.php:1982
1238
  msgid "Link Mask"
1239
  msgstr ""
1240
 
1241
+ #: modules/class.su-module.php:2826
1242
  msgid "Link Mask (Disabled)"
1243
  msgstr ""
1244
 
1245
+ #: modules/class.su-module.php:2831
1246
  msgid "A Deleted Link Mask"
1247
  msgstr ""
1248
 
1249
+ #: modules/class.su-module.php:2861
1250
  msgid "Type a URL or start typing the name of an item on your site"
1251
  msgstr ""
1252
 
1253
+ #: modules/class.su-module.php:2874
1254
  msgid "Remove this location from this textbox"
1255
  msgstr ""
1256
 
1257
+ #: modules/class.su-module.php:2874
1258
  msgid "X"
1259
  msgstr ""
1260
 
1261
+ #: modules/class.su-module.php:2983 modules/sds-blog/sds-blog.php:138
1262
  #, php-format
1263
  msgid "<strong>RSS Error</strong>: %s"
1264
  msgstr ""
1265
 
1266
+ #: modules/class.su-module.php:2999 modules/sds-blog/sds-blog.php:154
1267
  msgid ""
1268
  "An error has occurred, which probably means the feed is down. Try again "
1269
  "later."
1898
  msgstr ""
1899
 
1900
  #: modules/meta/meta-keywords.php:38 modules/meta/meta-robots.php:22
1901
+ #: modules/opengraph/opengraph.php:350
1902
  msgid "Sitewide Values"
1903
  msgstr ""
1904
 
1905
  #: modules/meta/meta-keywords.php:39 modules/noindex/noindex.php:50
1906
+ #: modules/opengraph/opengraph.php:351
1907
  msgid "Default Values"
1908
  msgstr ""
1909
 
2368
  msgstr ""
2369
 
2370
  #: modules/noindex/noindex.php:69 modules/noindex/noindex.php:80
2371
+ #: modules/opengraph/opengraph.php:321 modules/opengraph/opengraph.php:452
2372
+ #: modules/opengraph/opengraph.php:453
2373
  msgid "Use default"
2374
  msgstr ""
2375
 
2460
  msgid "Open Graph"
2461
  msgstr ""
2462
 
2463
+ #: modules/opengraph/opengraph.php:323
2464
  msgid "Type"
2465
  msgstr ""
2466
 
2467
+ #: modules/opengraph/opengraph.php:328
2468
  msgid "Title"
2469
  msgstr ""
2470
 
2471
+ #: modules/opengraph/opengraph.php:333
2472
  msgid "Description"
2473
  msgstr ""
2474
 
2475
+ #: modules/opengraph/opengraph.php:338
2476
  msgid "Image"
2477
  msgstr ""
2478
 
2479
+ #: modules/opengraph/opengraph.php:361
2480
  msgid "Site Name"
2481
  msgstr ""
2482
 
2483
+ #: modules/opengraph/opengraph.php:362
2484
  msgid "Facebook App ID"
2485
  msgstr ""
2486
 
2487
+ #: modules/opengraph/opengraph.php:363
2488
  msgid "@username of website"
2489
  msgstr ""
2490
 
2491
+ #: modules/opengraph/opengraph.php:364
2492
  msgid "Same as twitter:site, but the user&#8217;s Twitter ID"
2493
  msgstr ""
2494
 
2495
+ #: modules/opengraph/opengraph.php:365
2496
  msgid "@username of content creator"
2497
  msgstr ""
2498
 
2499
+ #: modules/opengraph/opengraph.php:366
2500
  msgid "Twitter user ID of content creator"
2501
  msgstr ""
2502
 
2503
+ #: modules/opengraph/opengraph.php:367
2504
  msgid "Description of content (maximum 200 characters)"
2505
  msgstr ""
2506
 
2507
+ #: modules/opengraph/opengraph.php:368
2508
  msgid "Title of content (maximum 70 characters)"
2509
  msgstr ""
2510
 
2511
+ #: modules/opengraph/opengraph.php:369
2512
  msgid "URL of image to use in the card. Image must be less than 1MB in size."
2513
  msgstr ""
2514
 
2515
+ #: modules/opengraph/opengraph.php:370
2516
  msgid "Width of image in pixels"
2517
  msgstr ""
2518
 
2519
+ #: modules/opengraph/opengraph.php:371
2520
  msgid "Height of image in pixels"
2521
  msgstr ""
2522
 
2523
+ #: modules/opengraph/opengraph.php:372
2524
  msgid ""
2525
  "Top customizable data field, can be a relatively short string (ie \"$3.99\")"
2526
  msgstr ""
2527
 
2528
+ #: modules/opengraph/opengraph.php:373 modules/opengraph/opengraph.php:375
2529
  msgid ""
2530
  "Customizable label or units for the information in twitter:data1 (best "
2531
  "practice: use all caps)"
2532
  msgstr ""
2533
 
2534
+ #: modules/opengraph/opengraph.php:374
2535
  msgid ""
2536
  "Bottom customizable data field, can be a relatively short string (ie "
2537
  "\"Seattle, WA\")"
2538
  msgstr ""
2539
 
2540
+ #: modules/opengraph/opengraph.php:376
2541
  msgid "1st image in the gallery. Images must be less than 1MB in size."
2542
  msgstr ""
2543
 
2544
+ #: modules/opengraph/opengraph.php:377
2545
  msgid "2nd image in the gallery. Images must be less than 1MB in size."
2546
  msgstr ""
2547
 
2548
+ #: modules/opengraph/opengraph.php:378
2549
  msgid "3rd image in the gallery. Images must be less than 1MB in size."
2550
  msgstr ""
2551
 
2552
+ #: modules/opengraph/opengraph.php:379
2553
  msgid "4th image in the gallery. Images must be less than 1MB in size."
2554
  msgstr ""
2555
 
2556
+ #: modules/opengraph/opengraph.php:380
2557
  msgid " \tHTTPS URL of player iframe"
2558
  msgstr ""
2559
 
2560
+ #: modules/opengraph/opengraph.php:381
2561
  msgid "Width of iframe in pixels"
2562
  msgstr ""
2563
 
2564
+ #: modules/opengraph/opengraph.php:382
2565
  msgid "Height of iframe in pixels"
2566
  msgstr ""
2567
 
2568
+ #: modules/opengraph/opengraph.php:383
2569
  msgid "URL to raw video or audio stream"
2570
  msgstr ""
2571
 
2572
+ #: modules/opengraph/opengraph.php:384
2573
  msgid "Name of your iPhone app"
2574
  msgstr ""
2575
 
2576
+ #: modules/opengraph/opengraph.php:385
2577
  msgid "Your app ID in the iTunes App Store (Note: NOT your bundle ID)"
2578
  msgstr ""
2579
 
2580
+ #: modules/opengraph/opengraph.php:386
2581
  msgid ""
2582
  "Your app&#8217;s custom URL scheme (you must include \"://\" after your "
2583
  "scheme name)"
2584
  msgstr ""
2585
 
2586
+ #: modules/opengraph/opengraph.php:387
2587
  msgid "Name of your iPad optimized app"
2588
  msgstr ""
2589
 
2590
+ #: modules/opengraph/opengraph.php:388
2591
  msgid "Your app ID in the iTunes App Store"
2592
  msgstr ""
2593
 
2594
+ #: modules/opengraph/opengraph.php:389
2595
  msgid "Your app&#8217;s custom URL scheme"
2596
  msgstr ""
2597
 
2598
+ #: modules/opengraph/opengraph.php:390
2599
  msgid "Name of your Android app"
2600
  msgstr ""
2601
 
2602
+ #: modules/opengraph/opengraph.php:391
2603
  msgid "Your app ID in the Google Play Store"
2604
  msgstr ""
2605
 
2606
+ #: modules/opengraph/opengraph.php:392
2607
  msgid "Your app#8217;s custom URL scheme"
2608
  msgstr ""
2609
 
2610
+ #: modules/opengraph/opengraph.php:399
2611
  msgid "Default Types"
2612
  msgstr ""
2613
 
2614
+ #: modules/opengraph/opengraph.php:401
2615
  msgid "Post Type"
2616
  msgstr ""
2617
 
2618
+ #: modules/opengraph/opengraph.php:402
2619
  msgid "Open Graph Type"
2620
  msgstr ""
2621
 
2622
+ #: modules/opengraph/opengraph.php:403
2623
  msgid "Twitter Type"
2624
  msgstr ""
2625
 
2626
+ #: modules/opengraph/opengraph.php:418 modules/opengraph/opengraph.php:423
2627
  msgid "Default Image"
2628
  msgstr ""
2629
 
2630
+ #: modules/opengraph/opengraph.php:421
2631
  msgid ""
2632
  "In the box below, you can specify an image URL or an image from your media "
2633
  "library to use as a default image in the event that there is no image "
2634
  "otherwise specified for a given webpage on your site."
2635
  msgstr ""
2636
 
2637
+ #: modules/opengraph/opengraph.php:430
2638
  msgid "Include author data for posts"
2639
  msgstr ""
2640
 
2641
+ #: modules/opengraph/opengraph.php:430
2642
  msgid "Open Graph Data"
2643
  msgstr ""
2644
 
2645
+ #: modules/opengraph/opengraph.php:432
2646
  msgid "Use the non-validating code prescribed by Open Graph and Twitter"
2647
  msgstr ""
2648
 
2649
+ #: modules/opengraph/opengraph.php:433
2650
  msgid "Alter the code to validate as XHTML"
2651
  msgstr ""
2652
 
2653
+ #: modules/opengraph/opengraph.php:434
2654
  msgid "Alter the code to validate as HTML5"
2655
  msgstr ""
2656
 
2657
+ #: modules/opengraph/opengraph.php:435
2658
  msgid "HTML Validation"
2659
  msgstr ""
2660
 
2661
+ #: modules/opengraph/opengraph.php:441 modules/titles/titles.php:91
2662
  msgid "Blog Homepage Title"
2663
  msgstr ""
2664
 
2665
+ #: modules/opengraph/opengraph.php:442
2666
  msgid "Blog Homepage Description"
2667
  msgstr ""
2668
 
2669
+ #: modules/opengraph/opengraph.php:443
2670
  msgid "Blog Homepage Image"
2671
  msgstr ""
2672
 
2673
+ #: modules/opengraph/opengraph.php:449 modules/widgets/widgets.php:140
2674
  msgid "Title:"
2675
  msgstr ""
2676
 
2677
+ #: modules/opengraph/opengraph.php:450
2678
  msgid "Description:"
2679
  msgstr ""
2680
 
2681
+ #: modules/opengraph/opengraph.php:451
2682
  msgid "Image:"
2683
  msgstr ""
2684
 
2685
+ #: modules/opengraph/opengraph.php:452
2686
  msgid "Open Graph Type:"
2687
  msgstr ""
2688
 
2689
+ #: modules/opengraph/opengraph.php:453
2690
  msgid "Twitter Type:"
2691
  msgstr ""
2692
 
2693
+ #: modules/opengraph/opengraph.php:478
2694
  #, php-format
2695
  msgid "Featured Image: %s"
2696
  msgstr ""
2697
 
2698
+ #: modules/opengraph/opengraph.php:486
2699
  #: modules/rich-snippets/rich-snippets.php:357
2700
  msgid "None"
2701
  msgstr ""
2702
 
2703
+ #: modules/opengraph/opengraph.php:487
2704
  msgid "Internet"
2705
  msgstr ""
2706
 
2707
+ #: modules/opengraph/opengraph.php:488
2708
  msgid "Article"
2709
  msgstr ""
2710
 
2711
+ #: modules/opengraph/opengraph.php:489
2712
  msgid "Blog"
2713
  msgstr ""
2714
 
2715
+ #: modules/opengraph/opengraph.php:490
2716
  msgid "Profile"
2717
  msgstr ""
2718
 
2719
+ #: modules/opengraph/opengraph.php:491
2720
  msgid "Website"
2721
  msgstr ""
2722
 
2723
+ #: modules/opengraph/opengraph.php:492
2724
  msgid "Products"
2725
  msgstr ""
2726
 
2727
+ #: modules/opengraph/opengraph.php:493
2728
  msgid "Book"
2729
  msgstr ""
2730
 
2731
+ #: modules/opengraph/opengraph.php:494
2732
  msgid "Music"
2733
  msgstr ""
2734
 
2735
+ #: modules/opengraph/opengraph.php:495
2736
  msgid "Album"
2737
  msgstr ""
2738
 
2739
+ #: modules/opengraph/opengraph.php:496
2740
  msgid "Playlist"
2741
  msgstr ""
2742
 
2743
+ #: modules/opengraph/opengraph.php:497
2744
  msgid "Radio Station"
2745
  msgstr ""
2746
 
2747
+ #: modules/opengraph/opengraph.php:498
2748
  msgid "Song"
2749
  msgstr ""
2750
 
2751
+ #: modules/opengraph/opengraph.php:499
2752
  msgid "Videos"
2753
  msgstr ""
2754
 
2755
+ #: modules/opengraph/opengraph.php:500
2756
  msgid "Movie"
2757
  msgstr ""
2758
 
2759
+ #: modules/opengraph/opengraph.php:501
2760
  msgid "TV Episode"
2761
  msgstr ""
2762
 
2763
+ #: modules/opengraph/opengraph.php:502
2764
  msgid "TV Show"
2765
  msgstr ""
2766
 
2767
+ #: modules/opengraph/opengraph.php:503
2768
  msgid "Video"
2769
  msgstr ""
2770
 
2771
+ #: modules/opengraph/opengraph.php:510
2772
  msgid "Summary"
2773
  msgstr ""
2774
 
2775
+ #: modules/opengraph/opengraph.php:511
2776
  msgid "Product"
2777
  msgstr ""
2778
 
2779
+ #: modules/opengraph/opengraph.php:512
2780
  #: modules/rich-snippets/rich-snippets.php:120
2781
  msgid "Photo"
2782
  msgstr ""
2783
 
2784
+ #: modules/opengraph/opengraph.php:513
2785
  msgid "Summary Large Image"
2786
  msgstr ""
2787
 
2788
+ #: modules/opengraph/opengraph.php:514
2789
  msgid "Gallery"
2790
  msgstr ""
2791
 
2792
+ #: modules/opengraph/opengraph.php:515
2793
  msgid "Player"
2794
  msgstr ""
2795
 
2796
+ #: modules/opengraph/opengraph.php:516
2797
  msgid "App"
2798
  msgstr ""
2799
 
2800
+ #: modules/opengraph/opengraph.php:538
2801
  msgid "Twitter Handle"
2802
  msgstr ""
2803
 
2804
+ #: modules/opengraph/opengraph.php:547
2805
  msgid ""
2806
  "\n"
2807
  "<ul>\n"
translations/seo-ultimate.pot CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: SEO Ultimate v7.6.5.7\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
- "POT-Creation-Date: 2015-06-29 20:58+0100\n"
8
- "PO-Revision-Date: 2015-06-29 20:58+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
@@ -56,7 +56,7 @@ msgstr ""
56
  msgid "Log"
57
  msgstr ""
58
 
59
- #: modules/404s/fofs-log.php:118 modules/class.su-module.php:1163
60
  msgid "Actions"
61
  msgstr ""
62
 
@@ -149,7 +149,7 @@ msgstr ""
149
 
150
  #: modules/404s/fofs-settings.php:17
151
  #: modules/internal-link-aliases/internal-link-aliases.php:43
152
- #: modules/opengraph/opengraph.php:351 modules/titles/titles.php:41
153
  msgid "Settings"
154
  msgstr ""
155
 
@@ -203,7 +203,7 @@ msgstr ""
203
  #: modules/meta/meta-keywords.php:178 modules/meta/meta-robots.php:52
204
  #: modules/meta/webmaster-verify.php:95 modules/meta/webmaster-verify.php:101
205
  #: modules/more-links/more-links.php:104 modules/more-links/more-links.php:111
206
- #: modules/opengraph/opengraph.php:545
207
  #: modules/rich-snippets/rich-snippets.php:410
208
  #: modules/rich-snippets/rich-snippets.php:417
209
  #: modules/settings/settings.php:63
@@ -1172,98 +1172,98 @@ msgstr ""
1172
  msgid "&raquo;"
1173
  msgstr ""
1174
 
1175
- #: modules/class.su-module.php:1150
1176
  #, php-format
1177
  msgid "Displaying %s&#8211;%s of %s"
1178
  msgstr ""
1179
 
1180
- #: modules/class.su-module.php:1164
1181
  msgid "ID"
1182
  msgstr ""
1183
 
1184
- #: modules/class.su-module.php:1217
1185
  msgid "View"
1186
  msgstr ""
1187
 
1188
- #: modules/class.su-module.php:1219
1189
  msgid "Edit"
1190
  msgstr ""
1191
 
1192
- #: modules/class.su-module.php:1389
1193
  msgid "Settings updated."
1194
  msgstr ""
1195
 
1196
- #: modules/class.su-module.php:1410
1197
  msgid "Save Changes"
1198
  msgstr ""
1199
 
1200
- #: modules/class.su-module.php:1897
1201
  msgid ""
1202
  "Are you sure you want to replace the textbox contents with this default "
1203
  "value?"
1204
  msgstr ""
1205
 
1206
- #: modules/class.su-module.php:1926 modules/settings/settings-data.php:23
1207
  msgid "Reset"
1208
  msgstr ""
1209
 
1210
- #: modules/class.su-module.php:2778 modules/class.su-module.php:2790
1211
  #, php-format
1212
  msgid "A Deleted %s"
1213
  msgstr ""
1214
 
1215
- #: modules/class.su-module.php:2780
1216
  msgid "A Deleted Post"
1217
  msgstr ""
1218
 
1219
- #: modules/class.su-module.php:2795
1220
  msgid "A Deleted Term"
1221
  msgstr ""
1222
 
1223
- #: modules/class.su-module.php:2801 modules/meta/meta-descriptions.php:31
1224
- #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:352
1225
  #: plugin/class.seo-ultimate.php:1876
1226
  msgid "Blog Homepage"
1227
  msgstr ""
1228
 
1229
- #: modules/class.su-module.php:2806 plugin/class.seo-ultimate.php:1952
1230
  msgid "Author"
1231
  msgstr ""
1232
 
1233
- #: modules/class.su-module.php:2808
1234
  msgid "A Deleted User"
1235
  msgstr ""
1236
 
1237
- #: modules/class.su-module.php:2823 plugin/class.seo-ultimate.php:1982
1238
  msgid "Link Mask"
1239
  msgstr ""
1240
 
1241
- #: modules/class.su-module.php:2825
1242
  msgid "Link Mask (Disabled)"
1243
  msgstr ""
1244
 
1245
- #: modules/class.su-module.php:2830
1246
  msgid "A Deleted Link Mask"
1247
  msgstr ""
1248
 
1249
- #: modules/class.su-module.php:2860
1250
  msgid "Type a URL or start typing the name of an item on your site"
1251
  msgstr ""
1252
 
1253
- #: modules/class.su-module.php:2873
1254
  msgid "Remove this location from this textbox"
1255
  msgstr ""
1256
 
1257
- #: modules/class.su-module.php:2873
1258
  msgid "X"
1259
  msgstr ""
1260
 
1261
- #: modules/class.su-module.php:2982 modules/sds-blog/sds-blog.php:138
1262
  #, php-format
1263
  msgid "<strong>RSS Error</strong>: %s"
1264
  msgstr ""
1265
 
1266
- #: modules/class.su-module.php:2998 modules/sds-blog/sds-blog.php:154
1267
  msgid ""
1268
  "An error has occurred, which probably means the feed is down. Try again "
1269
  "later."
@@ -1898,12 +1898,12 @@ msgid "Meta Keywords"
1898
  msgstr ""
1899
 
1900
  #: modules/meta/meta-keywords.php:38 modules/meta/meta-robots.php:22
1901
- #: modules/opengraph/opengraph.php:349
1902
  msgid "Sitewide Values"
1903
  msgstr ""
1904
 
1905
  #: modules/meta/meta-keywords.php:39 modules/noindex/noindex.php:50
1906
- #: modules/opengraph/opengraph.php:350
1907
  msgid "Default Values"
1908
  msgstr ""
1909
 
@@ -2368,8 +2368,8 @@ msgid "Noindex"
2368
  msgstr ""
2369
 
2370
  #: modules/noindex/noindex.php:69 modules/noindex/noindex.php:80
2371
- #: modules/opengraph/opengraph.php:320 modules/opengraph/opengraph.php:451
2372
- #: modules/opengraph/opengraph.php:452
2373
  msgid "Use default"
2374
  msgstr ""
2375
 
@@ -2460,348 +2460,348 @@ msgstr ""
2460
  msgid "Open Graph"
2461
  msgstr ""
2462
 
2463
- #: modules/opengraph/opengraph.php:322
2464
  msgid "Type"
2465
  msgstr ""
2466
 
2467
- #: modules/opengraph/opengraph.php:327
2468
  msgid "Title"
2469
  msgstr ""
2470
 
2471
- #: modules/opengraph/opengraph.php:332
2472
  msgid "Description"
2473
  msgstr ""
2474
 
2475
- #: modules/opengraph/opengraph.php:337
2476
  msgid "Image"
2477
  msgstr ""
2478
 
2479
- #: modules/opengraph/opengraph.php:360
2480
  msgid "Site Name"
2481
  msgstr ""
2482
 
2483
- #: modules/opengraph/opengraph.php:361
2484
  msgid "Facebook App ID"
2485
  msgstr ""
2486
 
2487
- #: modules/opengraph/opengraph.php:362
2488
  msgid "@username of website"
2489
  msgstr ""
2490
 
2491
- #: modules/opengraph/opengraph.php:363
2492
  msgid "Same as twitter:site, but the user&#8217;s Twitter ID"
2493
  msgstr ""
2494
 
2495
- #: modules/opengraph/opengraph.php:364
2496
  msgid "@username of content creator"
2497
  msgstr ""
2498
 
2499
- #: modules/opengraph/opengraph.php:365
2500
  msgid "Twitter user ID of content creator"
2501
  msgstr ""
2502
 
2503
- #: modules/opengraph/opengraph.php:366
2504
  msgid "Description of content (maximum 200 characters)"
2505
  msgstr ""
2506
 
2507
- #: modules/opengraph/opengraph.php:367
2508
  msgid "Title of content (maximum 70 characters)"
2509
  msgstr ""
2510
 
2511
- #: modules/opengraph/opengraph.php:368
2512
  msgid "URL of image to use in the card. Image must be less than 1MB in size."
2513
  msgstr ""
2514
 
2515
- #: modules/opengraph/opengraph.php:369
2516
  msgid "Width of image in pixels"
2517
  msgstr ""
2518
 
2519
- #: modules/opengraph/opengraph.php:370
2520
  msgid "Height of image in pixels"
2521
  msgstr ""
2522
 
2523
- #: modules/opengraph/opengraph.php:371
2524
  msgid ""
2525
  "Top customizable data field, can be a relatively short string (ie \"$3.99\")"
2526
  msgstr ""
2527
 
2528
- #: modules/opengraph/opengraph.php:372 modules/opengraph/opengraph.php:374
2529
  msgid ""
2530
  "Customizable label or units for the information in twitter:data1 (best "
2531
  "practice: use all caps)"
2532
  msgstr ""
2533
 
2534
- #: modules/opengraph/opengraph.php:373
2535
  msgid ""
2536
  "Bottom customizable data field, can be a relatively short string (ie "
2537
  "\"Seattle, WA\")"
2538
  msgstr ""
2539
 
2540
- #: modules/opengraph/opengraph.php:375
2541
  msgid "1st image in the gallery. Images must be less than 1MB in size."
2542
  msgstr ""
2543
 
2544
- #: modules/opengraph/opengraph.php:376
2545
  msgid "2nd image in the gallery. Images must be less than 1MB in size."
2546
  msgstr ""
2547
 
2548
- #: modules/opengraph/opengraph.php:377
2549
  msgid "3rd image in the gallery. Images must be less than 1MB in size."
2550
  msgstr ""
2551
 
2552
- #: modules/opengraph/opengraph.php:378
2553
  msgid "4th image in the gallery. Images must be less than 1MB in size."
2554
  msgstr ""
2555
 
2556
- #: modules/opengraph/opengraph.php:379
2557
  msgid " \tHTTPS URL of player iframe"
2558
  msgstr ""
2559
 
2560
- #: modules/opengraph/opengraph.php:380
2561
  msgid "Width of iframe in pixels"
2562
  msgstr ""
2563
 
2564
- #: modules/opengraph/opengraph.php:381
2565
  msgid "Height of iframe in pixels"
2566
  msgstr ""
2567
 
2568
- #: modules/opengraph/opengraph.php:382
2569
  msgid "URL to raw video or audio stream"
2570
  msgstr ""
2571
 
2572
- #: modules/opengraph/opengraph.php:383
2573
  msgid "Name of your iPhone app"
2574
  msgstr ""
2575
 
2576
- #: modules/opengraph/opengraph.php:384
2577
  msgid "Your app ID in the iTunes App Store (Note: NOT your bundle ID)"
2578
  msgstr ""
2579
 
2580
- #: modules/opengraph/opengraph.php:385
2581
  msgid ""
2582
  "Your app&#8217;s custom URL scheme (you must include \"://\" after your "
2583
  "scheme name)"
2584
  msgstr ""
2585
 
2586
- #: modules/opengraph/opengraph.php:386
2587
  msgid "Name of your iPad optimized app"
2588
  msgstr ""
2589
 
2590
- #: modules/opengraph/opengraph.php:387
2591
  msgid "Your app ID in the iTunes App Store"
2592
  msgstr ""
2593
 
2594
- #: modules/opengraph/opengraph.php:388
2595
  msgid "Your app&#8217;s custom URL scheme"
2596
  msgstr ""
2597
 
2598
- #: modules/opengraph/opengraph.php:389
2599
  msgid "Name of your Android app"
2600
  msgstr ""
2601
 
2602
- #: modules/opengraph/opengraph.php:390
2603
  msgid "Your app ID in the Google Play Store"
2604
  msgstr ""
2605
 
2606
- #: modules/opengraph/opengraph.php:391
2607
  msgid "Your app#8217;s custom URL scheme"
2608
  msgstr ""
2609
 
2610
- #: modules/opengraph/opengraph.php:398
2611
  msgid "Default Types"
2612
  msgstr ""
2613
 
2614
- #: modules/opengraph/opengraph.php:400
2615
  msgid "Post Type"
2616
  msgstr ""
2617
 
2618
- #: modules/opengraph/opengraph.php:401
2619
  msgid "Open Graph Type"
2620
  msgstr ""
2621
 
2622
- #: modules/opengraph/opengraph.php:402
2623
  msgid "Twitter Type"
2624
  msgstr ""
2625
 
2626
- #: modules/opengraph/opengraph.php:417 modules/opengraph/opengraph.php:422
2627
  msgid "Default Image"
2628
  msgstr ""
2629
 
2630
- #: modules/opengraph/opengraph.php:420
2631
  msgid ""
2632
  "In the box below, you can specify an image URL or an image from your media "
2633
  "library to use as a default image in the event that there is no image "
2634
  "otherwise specified for a given webpage on your site."
2635
  msgstr ""
2636
 
2637
- #: modules/opengraph/opengraph.php:429
2638
  msgid "Include author data for posts"
2639
  msgstr ""
2640
 
2641
- #: modules/opengraph/opengraph.php:429
2642
  msgid "Open Graph Data"
2643
  msgstr ""
2644
 
2645
- #: modules/opengraph/opengraph.php:431
2646
  msgid "Use the non-validating code prescribed by Open Graph and Twitter"
2647
  msgstr ""
2648
 
2649
- #: modules/opengraph/opengraph.php:432
2650
  msgid "Alter the code to validate as XHTML"
2651
  msgstr ""
2652
 
2653
- #: modules/opengraph/opengraph.php:433
2654
  msgid "Alter the code to validate as HTML5"
2655
  msgstr ""
2656
 
2657
- #: modules/opengraph/opengraph.php:434
2658
  msgid "HTML Validation"
2659
  msgstr ""
2660
 
2661
- #: modules/opengraph/opengraph.php:440 modules/titles/titles.php:91
2662
  msgid "Blog Homepage Title"
2663
  msgstr ""
2664
 
2665
- #: modules/opengraph/opengraph.php:441
2666
  msgid "Blog Homepage Description"
2667
  msgstr ""
2668
 
2669
- #: modules/opengraph/opengraph.php:442
2670
  msgid "Blog Homepage Image"
2671
  msgstr ""
2672
 
2673
- #: modules/opengraph/opengraph.php:448 modules/widgets/widgets.php:140
2674
  msgid "Title:"
2675
  msgstr ""
2676
 
2677
- #: modules/opengraph/opengraph.php:449
2678
  msgid "Description:"
2679
  msgstr ""
2680
 
2681
- #: modules/opengraph/opengraph.php:450
2682
  msgid "Image:"
2683
  msgstr ""
2684
 
2685
- #: modules/opengraph/opengraph.php:451
2686
  msgid "Open Graph Type:"
2687
  msgstr ""
2688
 
2689
- #: modules/opengraph/opengraph.php:452
2690
  msgid "Twitter Type:"
2691
  msgstr ""
2692
 
2693
- #: modules/opengraph/opengraph.php:477
2694
  #, php-format
2695
  msgid "Featured Image: %s"
2696
  msgstr ""
2697
 
2698
- #: modules/opengraph/opengraph.php:485
2699
  #: modules/rich-snippets/rich-snippets.php:357
2700
  msgid "None"
2701
  msgstr ""
2702
 
2703
- #: modules/opengraph/opengraph.php:486
2704
  msgid "Internet"
2705
  msgstr ""
2706
 
2707
- #: modules/opengraph/opengraph.php:487
2708
  msgid "Article"
2709
  msgstr ""
2710
 
2711
- #: modules/opengraph/opengraph.php:488
2712
  msgid "Blog"
2713
  msgstr ""
2714
 
2715
- #: modules/opengraph/opengraph.php:489
2716
  msgid "Profile"
2717
  msgstr ""
2718
 
2719
- #: modules/opengraph/opengraph.php:490
2720
  msgid "Website"
2721
  msgstr ""
2722
 
2723
- #: modules/opengraph/opengraph.php:491
2724
  msgid "Products"
2725
  msgstr ""
2726
 
2727
- #: modules/opengraph/opengraph.php:492
2728
  msgid "Book"
2729
  msgstr ""
2730
 
2731
- #: modules/opengraph/opengraph.php:493
2732
  msgid "Music"
2733
  msgstr ""
2734
 
2735
- #: modules/opengraph/opengraph.php:494
2736
  msgid "Album"
2737
  msgstr ""
2738
 
2739
- #: modules/opengraph/opengraph.php:495
2740
  msgid "Playlist"
2741
  msgstr ""
2742
 
2743
- #: modules/opengraph/opengraph.php:496
2744
  msgid "Radio Station"
2745
  msgstr ""
2746
 
2747
- #: modules/opengraph/opengraph.php:497
2748
  msgid "Song"
2749
  msgstr ""
2750
 
2751
- #: modules/opengraph/opengraph.php:498
2752
  msgid "Videos"
2753
  msgstr ""
2754
 
2755
- #: modules/opengraph/opengraph.php:499
2756
  msgid "Movie"
2757
  msgstr ""
2758
 
2759
- #: modules/opengraph/opengraph.php:500
2760
  msgid "TV Episode"
2761
  msgstr ""
2762
 
2763
- #: modules/opengraph/opengraph.php:501
2764
  msgid "TV Show"
2765
  msgstr ""
2766
 
2767
- #: modules/opengraph/opengraph.php:502
2768
  msgid "Video"
2769
  msgstr ""
2770
 
2771
- #: modules/opengraph/opengraph.php:509
2772
  msgid "Summary"
2773
  msgstr ""
2774
 
2775
- #: modules/opengraph/opengraph.php:510
2776
  msgid "Product"
2777
  msgstr ""
2778
 
2779
- #: modules/opengraph/opengraph.php:511
2780
  #: modules/rich-snippets/rich-snippets.php:120
2781
  msgid "Photo"
2782
  msgstr ""
2783
 
2784
- #: modules/opengraph/opengraph.php:512
2785
  msgid "Summary Large Image"
2786
  msgstr ""
2787
 
2788
- #: modules/opengraph/opengraph.php:513
2789
  msgid "Gallery"
2790
  msgstr ""
2791
 
2792
- #: modules/opengraph/opengraph.php:514
2793
  msgid "Player"
2794
  msgstr ""
2795
 
2796
- #: modules/opengraph/opengraph.php:515
2797
  msgid "App"
2798
  msgstr ""
2799
 
2800
- #: modules/opengraph/opengraph.php:537
2801
  msgid "Twitter Handle"
2802
  msgstr ""
2803
 
2804
- #: modules/opengraph/opengraph.php:546
2805
  msgid ""
2806
  "\n"
2807
  "<ul>\n"
2
  # This file is distributed under the same license as the SEO Ultimate package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: SEO Ultimate v7.6.5.8\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/seo-ultimate\n"
7
+ "POT-Creation-Date: 2015-09-24 02:09+0100\n"
8
+ "PO-Revision-Date: 2015-09-24 02:09+0100\n"
9
  "Last-Translator: \n"
10
  "Language-Team: SEO Design Solutions <support@seodesignsolutions.com>\n"
11
  "Language: en_US\n"
56
  msgid "Log"
57
  msgstr ""
58
 
59
+ #: modules/404s/fofs-log.php:118 modules/class.su-module.php:1164
60
  msgid "Actions"
61
  msgstr ""
62
 
149
 
150
  #: modules/404s/fofs-settings.php:17
151
  #: modules/internal-link-aliases/internal-link-aliases.php:43
152
+ #: modules/opengraph/opengraph.php:352 modules/titles/titles.php:41
153
  msgid "Settings"
154
  msgstr ""
155
 
203
  #: modules/meta/meta-keywords.php:178 modules/meta/meta-robots.php:52
204
  #: modules/meta/webmaster-verify.php:95 modules/meta/webmaster-verify.php:101
205
  #: modules/more-links/more-links.php:104 modules/more-links/more-links.php:111
206
+ #: modules/opengraph/opengraph.php:546
207
  #: modules/rich-snippets/rich-snippets.php:410
208
  #: modules/rich-snippets/rich-snippets.php:417
209
  #: modules/settings/settings.php:63
1172
  msgid "&raquo;"
1173
  msgstr ""
1174
 
1175
+ #: modules/class.su-module.php:1151
1176
  #, php-format
1177
  msgid "Displaying %s&#8211;%s of %s"
1178
  msgstr ""
1179
 
1180
+ #: modules/class.su-module.php:1165
1181
  msgid "ID"
1182
  msgstr ""
1183
 
1184
+ #: modules/class.su-module.php:1218
1185
  msgid "View"
1186
  msgstr ""
1187
 
1188
+ #: modules/class.su-module.php:1220
1189
  msgid "Edit"
1190
  msgstr ""
1191
 
1192
+ #: modules/class.su-module.php:1390
1193
  msgid "Settings updated."
1194
  msgstr ""
1195
 
1196
+ #: modules/class.su-module.php:1411
1197
  msgid "Save Changes"
1198
  msgstr ""
1199
 
1200
+ #: modules/class.su-module.php:1898
1201
  msgid ""
1202
  "Are you sure you want to replace the textbox contents with this default "
1203
  "value?"
1204
  msgstr ""
1205
 
1206
+ #: modules/class.su-module.php:1927 modules/settings/settings-data.php:23
1207
  msgid "Reset"
1208
  msgstr ""
1209
 
1210
+ #: modules/class.su-module.php:2779 modules/class.su-module.php:2791
1211
  #, php-format
1212
  msgid "A Deleted %s"
1213
  msgstr ""
1214
 
1215
+ #: modules/class.su-module.php:2781
1216
  msgid "A Deleted Post"
1217
  msgstr ""
1218
 
1219
+ #: modules/class.su-module.php:2796
1220
  msgid "A Deleted Term"
1221
  msgstr ""
1222
 
1223
+ #: modules/class.su-module.php:2802 modules/meta/meta-descriptions.php:31
1224
+ #: modules/meta/meta-keywords.php:40 modules/opengraph/opengraph.php:353
1225
  #: plugin/class.seo-ultimate.php:1876
1226
  msgid "Blog Homepage"
1227
  msgstr ""
1228
 
1229
+ #: modules/class.su-module.php:2807 plugin/class.seo-ultimate.php:1952
1230
  msgid "Author"
1231
  msgstr ""
1232
 
1233
+ #: modules/class.su-module.php:2809
1234
  msgid "A Deleted User"
1235
  msgstr ""
1236
 
1237
+ #: modules/class.su-module.php:2824 plugin/class.seo-ultimate.php:1982
1238
  msgid "Link Mask"
1239
  msgstr ""
1240
 
1241
+ #: modules/class.su-module.php:2826
1242
  msgid "Link Mask (Disabled)"
1243
  msgstr ""
1244
 
1245
+ #: modules/class.su-module.php:2831
1246
  msgid "A Deleted Link Mask"
1247
  msgstr ""
1248
 
1249
+ #: modules/class.su-module.php:2861
1250
  msgid "Type a URL or start typing the name of an item on your site"
1251
  msgstr ""
1252
 
1253
+ #: modules/class.su-module.php:2874
1254
  msgid "Remove this location from this textbox"
1255
  msgstr ""
1256
 
1257
+ #: modules/class.su-module.php:2874
1258
  msgid "X"
1259
  msgstr ""
1260
 
1261
+ #: modules/class.su-module.php:2983 modules/sds-blog/sds-blog.php:138
1262
  #, php-format
1263
  msgid "<strong>RSS Error</strong>: %s"
1264
  msgstr ""
1265
 
1266
+ #: modules/class.su-module.php:2999 modules/sds-blog/sds-blog.php:154
1267
  msgid ""
1268
  "An error has occurred, which probably means the feed is down. Try again "
1269
  "later."
1898
  msgstr ""
1899
 
1900
  #: modules/meta/meta-keywords.php:38 modules/meta/meta-robots.php:22
1901
+ #: modules/opengraph/opengraph.php:350
1902
  msgid "Sitewide Values"
1903
  msgstr ""
1904
 
1905
  #: modules/meta/meta-keywords.php:39 modules/noindex/noindex.php:50
1906
+ #: modules/opengraph/opengraph.php:351
1907
  msgid "Default Values"
1908
  msgstr ""
1909
 
2368
  msgstr ""
2369
 
2370
  #: modules/noindex/noindex.php:69 modules/noindex/noindex.php:80
2371
+ #: modules/opengraph/opengraph.php:321 modules/opengraph/opengraph.php:452
2372
+ #: modules/opengraph/opengraph.php:453
2373
  msgid "Use default"
2374
  msgstr ""
2375
 
2460
  msgid "Open Graph"
2461
  msgstr ""
2462
 
2463
+ #: modules/opengraph/opengraph.php:323
2464
  msgid "Type"
2465
  msgstr ""
2466
 
2467
+ #: modules/opengraph/opengraph.php:328
2468
  msgid "Title"
2469
  msgstr ""
2470
 
2471
+ #: modules/opengraph/opengraph.php:333
2472
  msgid "Description"
2473
  msgstr ""
2474
 
2475
+ #: modules/opengraph/opengraph.php:338
2476
  msgid "Image"
2477
  msgstr ""
2478
 
2479
+ #: modules/opengraph/opengraph.php:361
2480
  msgid "Site Name"
2481
  msgstr ""
2482
 
2483
+ #: modules/opengraph/opengraph.php:362
2484
  msgid "Facebook App ID"
2485
  msgstr ""
2486
 
2487
+ #: modules/opengraph/opengraph.php:363
2488
  msgid "@username of website"
2489
  msgstr ""
2490
 
2491
+ #: modules/opengraph/opengraph.php:364
2492
  msgid "Same as twitter:site, but the user&#8217;s Twitter ID"
2493
  msgstr ""
2494
 
2495
+ #: modules/opengraph/opengraph.php:365
2496
  msgid "@username of content creator"
2497
  msgstr ""
2498
 
2499
+ #: modules/opengraph/opengraph.php:366
2500
  msgid "Twitter user ID of content creator"
2501
  msgstr ""
2502
 
2503
+ #: modules/opengraph/opengraph.php:367
2504
  msgid "Description of content (maximum 200 characters)"
2505
  msgstr ""
2506
 
2507
+ #: modules/opengraph/opengraph.php:368
2508
  msgid "Title of content (maximum 70 characters)"
2509
  msgstr ""
2510
 
2511
+ #: modules/opengraph/opengraph.php:369
2512
  msgid "URL of image to use in the card. Image must be less than 1MB in size."
2513
  msgstr ""
2514
 
2515
+ #: modules/opengraph/opengraph.php:370
2516
  msgid "Width of image in pixels"
2517
  msgstr ""
2518
 
2519
+ #: modules/opengraph/opengraph.php:371
2520
  msgid "Height of image in pixels"
2521
  msgstr ""
2522
 
2523
+ #: modules/opengraph/opengraph.php:372
2524
  msgid ""
2525
  "Top customizable data field, can be a relatively short string (ie \"$3.99\")"
2526
  msgstr ""
2527
 
2528
+ #: modules/opengraph/opengraph.php:373 modules/opengraph/opengraph.php:375
2529
  msgid ""
2530
  "Customizable label or units for the information in twitter:data1 (best "
2531
  "practice: use all caps)"
2532
  msgstr ""
2533
 
2534
+ #: modules/opengraph/opengraph.php:374
2535
  msgid ""
2536
  "Bottom customizable data field, can be a relatively short string (ie "
2537
  "\"Seattle, WA\")"
2538
  msgstr ""
2539
 
2540
+ #: modules/opengraph/opengraph.php:376
2541
  msgid "1st image in the gallery. Images must be less than 1MB in size."
2542
  msgstr ""
2543
 
2544
+ #: modules/opengraph/opengraph.php:377
2545
  msgid "2nd image in the gallery. Images must be less than 1MB in size."
2546
  msgstr ""
2547
 
2548
+ #: modules/opengraph/opengraph.php:378
2549
  msgid "3rd image in the gallery. Images must be less than 1MB in size."
2550
  msgstr ""
2551
 
2552
+ #: modules/opengraph/opengraph.php:379
2553
  msgid "4th image in the gallery. Images must be less than 1MB in size."
2554
  msgstr ""
2555
 
2556
+ #: modules/opengraph/opengraph.php:380
2557
  msgid " \tHTTPS URL of player iframe"
2558
  msgstr ""
2559
 
2560
+ #: modules/opengraph/opengraph.php:381
2561
  msgid "Width of iframe in pixels"
2562
  msgstr ""
2563
 
2564
+ #: modules/opengraph/opengraph.php:382
2565
  msgid "Height of iframe in pixels"
2566
  msgstr ""
2567
 
2568
+ #: modules/opengraph/opengraph.php:383
2569
  msgid "URL to raw video or audio stream"
2570
  msgstr ""
2571
 
2572
+ #: modules/opengraph/opengraph.php:384
2573
  msgid "Name of your iPhone app"
2574
  msgstr ""
2575
 
2576
+ #: modules/opengraph/opengraph.php:385
2577
  msgid "Your app ID in the iTunes App Store (Note: NOT your bundle ID)"
2578
  msgstr ""
2579
 
2580
+ #: modules/opengraph/opengraph.php:386
2581
  msgid ""
2582
  "Your app&#8217;s custom URL scheme (you must include \"://\" after your "
2583
  "scheme name)"
2584
  msgstr ""
2585
 
2586
+ #: modules/opengraph/opengraph.php:387
2587
  msgid "Name of your iPad optimized app"
2588
  msgstr ""
2589
 
2590
+ #: modules/opengraph/opengraph.php:388
2591
  msgid "Your app ID in the iTunes App Store"
2592
  msgstr ""
2593
 
2594
+ #: modules/opengraph/opengraph.php:389
2595
  msgid "Your app&#8217;s custom URL scheme"
2596
  msgstr ""
2597
 
2598
+ #: modules/opengraph/opengraph.php:390
2599
  msgid "Name of your Android app"
2600
  msgstr ""
2601
 
2602
+ #: modules/opengraph/opengraph.php:391
2603
  msgid "Your app ID in the Google Play Store"
2604
  msgstr ""
2605
 
2606
+ #: modules/opengraph/opengraph.php:392
2607
  msgid "Your app#8217;s custom URL scheme"
2608
  msgstr ""
2609
 
2610
+ #: modules/opengraph/opengraph.php:399
2611
  msgid "Default Types"
2612
  msgstr ""
2613
 
2614
+ #: modules/opengraph/opengraph.php:401
2615
  msgid "Post Type"
2616
  msgstr ""
2617
 
2618
+ #: modules/opengraph/opengraph.php:402
2619
  msgid "Open Graph Type"
2620
  msgstr ""
2621
 
2622
+ #: modules/opengraph/opengraph.php:403
2623
  msgid "Twitter Type"
2624
  msgstr ""
2625
 
2626
+ #: modules/opengraph/opengraph.php:418 modules/opengraph/opengraph.php:423
2627
  msgid "Default Image"
2628
  msgstr ""
2629
 
2630
+ #: modules/opengraph/opengraph.php:421
2631
  msgid ""
2632
  "In the box below, you can specify an image URL or an image from your media "
2633
  "library to use as a default image in the event that there is no image "
2634
  "otherwise specified for a given webpage on your site."
2635
  msgstr ""
2636
 
2637
+ #: modules/opengraph/opengraph.php:430
2638
  msgid "Include author data for posts"
2639
  msgstr ""
2640
 
2641
+ #: modules/opengraph/opengraph.php:430
2642
  msgid "Open Graph Data"
2643
  msgstr ""
2644
 
2645
+ #: modules/opengraph/opengraph.php:432
2646
  msgid "Use the non-validating code prescribed by Open Graph and Twitter"
2647
  msgstr ""
2648
 
2649
+ #: modules/opengraph/opengraph.php:433
2650
  msgid "Alter the code to validate as XHTML"
2651
  msgstr ""
2652
 
2653
+ #: modules/opengraph/opengraph.php:434
2654
  msgid "Alter the code to validate as HTML5"
2655
  msgstr ""
2656
 
2657
+ #: modules/opengraph/opengraph.php:435
2658
  msgid "HTML Validation"
2659
  msgstr ""
2660
 
2661
+ #: modules/opengraph/opengraph.php:441 modules/titles/titles.php:91
2662
  msgid "Blog Homepage Title"
2663
  msgstr ""
2664
 
2665
+ #: modules/opengraph/opengraph.php:442
2666
  msgid "Blog Homepage Description"
2667
  msgstr ""
2668
 
2669
+ #: modules/opengraph/opengraph.php:443
2670
  msgid "Blog Homepage Image"
2671
  msgstr ""
2672
 
2673
+ #: modules/opengraph/opengraph.php:449 modules/widgets/widgets.php:140
2674
  msgid "Title:"
2675
  msgstr ""
2676
 
2677
+ #: modules/opengraph/opengraph.php:450
2678
  msgid "Description:"
2679
  msgstr ""
2680
 
2681
+ #: modules/opengraph/opengraph.php:451
2682
  msgid "Image:"
2683
  msgstr ""
2684
 
2685
+ #: modules/opengraph/opengraph.php:452
2686
  msgid "Open Graph Type:"
2687
  msgstr ""
2688
 
2689
+ #: modules/opengraph/opengraph.php:453
2690
  msgid "Twitter Type:"
2691
  msgstr ""
2692
 
2693
+ #: modules/opengraph/opengraph.php:478
2694
  #, php-format
2695
  msgid "Featured Image: %s"
2696
  msgstr ""
2697
 
2698
+ #: modules/opengraph/opengraph.php:486
2699
  #: modules/rich-snippets/rich-snippets.php:357
2700
  msgid "None"
2701
  msgstr ""
2702
 
2703
+ #: modules/opengraph/opengraph.php:487
2704
  msgid "Internet"
2705
  msgstr ""
2706
 
2707
+ #: modules/opengraph/opengraph.php:488
2708
  msgid "Article"
2709
  msgstr ""
2710
 
2711
+ #: modules/opengraph/opengraph.php:489
2712
  msgid "Blog"
2713
  msgstr ""
2714
 
2715
+ #: modules/opengraph/opengraph.php:490
2716
  msgid "Profile"
2717
  msgstr ""
2718
 
2719
+ #: modules/opengraph/opengraph.php:491
2720
  msgid "Website"
2721
  msgstr ""
2722
 
2723
+ #: modules/opengraph/opengraph.php:492
2724
  msgid "Products"
2725
  msgstr ""
2726
 
2727
+ #: modules/opengraph/opengraph.php:493
2728
  msgid "Book"
2729
  msgstr ""
2730
 
2731
+ #: modules/opengraph/opengraph.php:494
2732
  msgid "Music"
2733
  msgstr ""
2734
 
2735
+ #: modules/opengraph/opengraph.php:495
2736
  msgid "Album"
2737
  msgstr ""
2738
 
2739
+ #: modules/opengraph/opengraph.php:496
2740
  msgid "Playlist"
2741
  msgstr ""
2742
 
2743
+ #: modules/opengraph/opengraph.php:497
2744
  msgid "Radio Station"
2745
  msgstr ""
2746
 
2747
+ #: modules/opengraph/opengraph.php:498
2748
  msgid "Song"
2749
  msgstr ""
2750
 
2751
+ #: modules/opengraph/opengraph.php:499
2752
  msgid "Videos"
2753
  msgstr ""
2754
 
2755
+ #: modules/opengraph/opengraph.php:500
2756
  msgid "Movie"
2757
  msgstr ""
2758
 
2759
+ #: modules/opengraph/opengraph.php:501
2760
  msgid "TV Episode"
2761
  msgstr ""
2762
 
2763
+ #: modules/opengraph/opengraph.php:502
2764
  msgid "TV Show"
2765
  msgstr ""
2766
 
2767
+ #: modules/opengraph/opengraph.php:503
2768
  msgid "Video"
2769
  msgstr ""
2770
 
2771
+ #: modules/opengraph/opengraph.php:510
2772
  msgid "Summary"
2773
  msgstr ""
2774
 
2775
+ #: modules/opengraph/opengraph.php:511
2776
  msgid "Product"
2777
  msgstr ""
2778
 
2779
+ #: modules/opengraph/opengraph.php:512
2780
  #: modules/rich-snippets/rich-snippets.php:120
2781
  msgid "Photo"
2782
  msgstr ""
2783
 
2784
+ #: modules/opengraph/opengraph.php:513
2785
  msgid "Summary Large Image"
2786
  msgstr ""
2787
 
2788
+ #: modules/opengraph/opengraph.php:514
2789
  msgid "Gallery"
2790
  msgstr ""
2791
 
2792
+ #: modules/opengraph/opengraph.php:515
2793
  msgid "Player"
2794
  msgstr ""
2795
 
2796
+ #: modules/opengraph/opengraph.php:516
2797
  msgid "App"
2798
  msgstr ""
2799
 
2800
+ #: modules/opengraph/opengraph.php:538
2801
  msgid "Twitter Handle"
2802
  msgstr ""
2803
 
2804
+ #: modules/opengraph/opengraph.php:547
2805
  msgid ""
2806
  "\n"
2807
  "<ul>\n"