PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.2.2
Permalink Manager Lite v2.2.2
2.5.4 2.5.3.4 2.2.18 2.2.19.2 2.2.19.3 2.2.19.3.1 2.2.2 2.2.20 2.2.20.1 2.2.20.3 2.2.4 2.2.5 2.2.6 2.2.7.2 2.2.7.3 2.2.7.5 2.2.7.6 2.2.8.4 2.2.8.5 2.2.8.6 2.2.8.7 2.2.8.9 2.2.9.1 2.2.9.2 2.2.9.2.1 2.2.9.3 2.2.9.4 2.2.9.6 2.2.9.7 2.2.9.9 2.3.0 2.3.1.1 2.4.0 2.4.1 2.4.1.2 2.4.1.3 2.4.1.4 2.4.1.5 2.4.1.6 2.4.2 2.4.2.1 2.4.3 2.4.3.1 2.4.3.2 2.4.3.3 2.4.3.4 2.4.4 2.4.4.1 2.4.4.2 2.4.4.3 2.5.0 2.5.1 2.5.1.1 2.5.1.2 2.5.1.3 2.5.1.4 2.5.2 2.5.2.1 2.5.2.2 2.5.2.3 2.5.2.4 2.5.3 2.5.3.1 2.5.3.2 2.5.3.3 trunk 0.2 0.3 0.3.1 0.3.2 0.3.3 0.3.4 0.4 0.4.1 0.4.2 0.4.3 0.4.4 0.4.6 0.4.7 0.4.8 0.4.9 0.5.3 0.5.4 1.0.0 1.0.1 1.0.4 1.1.0 1.1.1 1.1.2 1.11.6.3 2.0.0 2.0.3 2.0.4 2.0.4.3 2.0.5.1 2.0.5.2 2.0.5.3 2.0.5.3.1 2.0.5.4 2.0.5.4a 2.0.5.5 2.0.5.6 2.0.5.6.1 2.0.5.7 2.0.5.9a 2.0.6.2.1 2.0.6.2a 2.0.6.3 2.1.0 2.1.1 2.1.2.4 2.2.0 2.2.1.1 2.2.1.2 2.2.11 2.2.12 2.2.13.1 2.2.14 2.2.15.1 2.2.16 2.2.17
permalink-manager / includes / core / permalink-manager-admin-functions.php
permalink-manager / includes / core Last commit date
permalink-manager-actions.php 7 years ago permalink-manager-admin-functions.php 7 years ago permalink-manager-core-functions.php 7 years ago permalink-manager-gutenberg.php 7 years ago permalink-manager-helper-functions.php 7 years ago permalink-manager-third-parties.php 7 years ago permalink-manager-uri-functions-post.php 7 years ago
permalink-manager-admin-functions.php
993 lines
1 <?php
2
3 /**
4 * Additional back-end functions related to Wordpress Dashboard UI
5 */
6 class Permalink_Manager_Admin_Functions extends Permalink_Manager_Class {
7
8 public $menu_name, $sections, $active_section, $active_subsection;
9 public $plugin_basename = PERMALINK_MANAGER_BASENAME;
10
11 public function __construct() {
12 add_action( 'admin_menu', array($this, 'add_menu_page') );
13 add_action( 'admin_init', array($this, 'init') );
14 add_action( 'admin_init', array($this, 'redirect_customizer') );
15
16 add_action( 'admin_notices', array($this, 'display_plugin_notices'));
17 add_action( 'admin_notices', array($this, 'display_global_notices'));
18 add_action( 'wp_ajax_dismissed_notice_handler', array($this, 'hide_global_notice') );
19
20 add_filter( 'default_hidden_columns', array($this, 'quick_edit_hide_column'), 10, 2 );
21
22 add_action( 'wp_ajax_detect_duplicates', array($this, 'ajax_detect_duplicates') );
23 }
24
25 /**
26 * Hooks that should be triggered with "admin_init"
27 */
28 public function init() {
29 // Additional link in "Plugins" page
30 add_filter( "plugin_action_links_{$this->plugin_basename}", array($this, "plugins_page_links") );
31
32 // Detect current section
33 $this->sections = apply_filters('permalink_manager_sections', array());
34 $this->get_current_section();
35 }
36
37 /**
38 * Redirect custom permalinks to the native ones in Customizer editor
39 */
40 public function redirect_customizer() {
41 if(strpos($_SERVER['REQUEST_URI'], 'customize.php') && !empty($_GET['url'])) {
42 $old_url = $_GET['url'];
43 $old_path = trim(parse_url($old_url, PHP_URL_PATH), "/");
44 $old_query = parse_url($old_url, PHP_URL_QUERY);
45
46 // Detect the post/term
47 $element = Permalink_Manager_Core_Functions::detect_post(null, $old_url, true);
48
49 if(!empty($element->ID)) {
50 $correct_permalink = get_permalink($element->ID);
51 } else if(!empty($element->term_id)) {
52 $correct_permalink = get_term_link($element, $element->taxonomy);
53 }
54
55 // Get the full URL
56 if(!empty($correct_permalink)) {
57 $new_path = trim(parse_url($correct_permalink, PHP_URL_PATH), "/");
58
59 $new_customize_url = wp_customize_url();
60 $new_customize_url .= "?" . str_replace(urlencode($old_path), urlencode($new_path), parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY));
61 $new_customize_url .= ($old_query) ? "&{$old_query}" : "";
62
63 // Redirect to customizer with native permalink
64 if($old_path !== $new_path) {
65 wp_safe_redirect($new_customize_url);
66 exit();
67 }
68 }
69 }
70 }
71
72 /**
73 * Get current section (only in plugin sections)
74 */
75 public function get_current_section() {
76 global $active_section, $active_subsection, $current_admin_tax;
77
78 // 1. Get current section
79 if(isset($_GET['page']) && $_GET['page'] == PERMALINK_MANAGER_PLUGIN_SLUG) {
80 if(isset($_POST['section'])) {
81 $this->active_section = $_POST['section'];
82 } else if(isset($_GET['section'])) {
83 $this->active_section = $_GET['section'];
84 } else {
85 $sections_names = array_keys($this->sections);
86 $this->active_section = $sections_names[0];
87 }
88 }
89
90 // 2. Get current subsection
91 if($this->active_section && isset($this->sections[$this->active_section]['subsections'])) {
92 if(isset($_POST['subsection'])) {
93 $this->active_subsection = $_POST['subsection'];
94 } else if(isset($_GET['subsection'])) {
95 $this->active_subsection = $_GET['subsection'];
96 } else {
97 $subsections_names = array_keys($this->sections[$this->active_section]['subsections']);
98 $this->active_subsection = $subsections_names[0];
99 }
100 }
101
102 // Check if current admin page is related to taxonomies
103 if(substr($this->active_subsection, 0, 4) == 'tax_') {
104 $current_admin_tax = substr($this->active_subsection, 4, strlen($this->active_subsection));
105 } else {
106 $current_admin_tax = false;
107 }
108
109 // Set globals
110 $active_section = $this->active_section;
111 $active_subsection = $this->active_subsection;
112 }
113
114 /**
115 * Add menu page.
116 */
117 public function add_menu_page() {
118 $this->menu_name = add_management_page( __('Permalink Manager', 'permalink-manager'), __('Permalink Manager', 'permalink-manager'), 'manage_options', PERMALINK_MANAGER_PLUGIN_SLUG, array($this, 'display_section') );
119
120 add_action( 'admin_init', array($this, 'enqueue_styles' ) );
121 add_action( 'admin_init', array($this, 'enqueue_scripts' ) );
122 }
123
124 /**
125 * Register the CSS file for the dashboard.
126 */
127 public function enqueue_styles() {
128 wp_enqueue_style( 'permalink-manager-plugins', PERMALINK_MANAGER_URL . '/out/permalink-manager-plugins.css', array(), PERMALINK_MANAGER_VERSION, 'all' );
129 wp_enqueue_style( 'permalink-manager', PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.css', array('permalink-manager-plugins'), PERMALINK_MANAGER_VERSION, 'all' );
130 }
131
132 /**
133 * Register the JavaScript file for the dashboard.
134 */
135 public function enqueue_scripts() {
136 wp_enqueue_script( 'permalink-manager-plugins', PERMALINK_MANAGER_URL . '/out/permalink-manager-plugins.js', array( 'jquery', ), PERMALINK_MANAGER_VERSION, false );
137 wp_enqueue_script( 'permalink-manager', PERMALINK_MANAGER_URL . '/out/permalink-manager-admin.js', array( 'jquery', 'permalink-manager-plugins' ), PERMALINK_MANAGER_VERSION, false );
138
139 wp_localize_script( 'permalink-manager', 'permalink_manager', array('ajax_url' => admin_url('admin-ajax.php'), 'url' => PERMALINK_MANAGER_URL, 'spinners' => admin_url('images')) );
140
141 }
142
143 /**
144 * Get admin url for the plugin
145 */
146 public static function get_admin_url($append = '') {
147 //return menu_page_url(PERMALINK_MANAGER_PLUGIN_SLUG, false) . $append;
148 $admin_page = sprintf("tools.php?page=%s", PERMALINK_MANAGER_PLUGIN_SLUG . $append);
149
150 return admin_url($admin_page);
151 }
152
153 /**
154 * Additional links on "Plugins" page
155 */
156 public function plugins_page_links($links) {
157 $links[] = sprintf('<a href="%s">%s</a>', $this->get_admin_url(), __( 'URI Editor', 'permalink-manager' ));
158 if(!defined('PERMALINK_MANAGER_PRO')) {
159 $links[] = sprintf('<a href="%s" target="_blank">%s</a>', PERMALINK_MANAGER_WEBSITE, __( 'Buy Permalink Manager Pro', 'permalink-manager' ));
160 }
161 return $links;
162 }
163
164 /**
165 * Generate the fields
166 */
167 static public function generate_option_field($input_name, $args) {
168 global $permalink_manager_options, $permalink_manager_permastructs;
169
170 // Reset $fields variables
171 $fields = $section_name = $field_name = '';
172
173 // Allow to filter the $args
174 $args = apply_filters('permalink_manager_field_args', $args, $input_name);
175
176 $field_type = (isset($args['type'])) ? $args['type'] : 'text';
177 $default = (isset($args['default'])) ? $args['default'] : '';
178 $label = (isset($args['label'])) ? $args['label'] : '';
179 $rows = (isset($args['rows'])) ? "rows=\"{$rows}\"" : "rows=\"5\"";
180 $container_class = (isset($args['container_class'])) ? " class=\"{$args['container_class']} field-container\"" : " class=\"field-container\"";
181 $description = (isset($args['before_description'])) ? $args['before_description'] : "";
182 $description .= (isset($args['description'])) ? "<p class=\"field-description description\">{$args['description']}</p>" : "";
183 $description .= (isset($args['after_description'])) ? $args['after_description'] : "";
184 $description .= (isset($args['pro'])) ? sprintf("<p class=\"field-description description alert info\">%s</p>", (Permalink_Manager_Admin_Functions::pro_text(true))) : "";
185 $append_content = (isset($args['append_content'])) ? "{$args['append_content']}" : "";
186
187 // Input attributes
188 $input_atts = (isset($args['input_class'])) ? "class='{$args['input_class']}'" : '';
189 $input_atts .= (isset($args['readonly'])) ? " readonly='readonly'" : '';
190 $input_atts .= (isset($args['disabled'])) ? " disabled='disabled'" : '';
191 $input_atts .= (isset($args['placeholder'])) ? " placeholder='{$args['placeholder']}'" : '';
192 $input_atts .= (isset($args['extra_atts'])) ? " {$args['extra_atts']}" : '';
193
194 // Get the field value (if it is not set in $args)
195 if(isset($args['value']) && empty($args['value']) == false) {
196 $value = $args['value'];
197 } else {
198 // Extract the section and field name from $input_name
199 preg_match("/(.*)\[(.*)\]/", $input_name, $field_section_and_name);
200
201 if($field_section_and_name) {
202 $section_name = $field_section_and_name[1];
203 $field_name = $field_section_and_name[2];
204 $value = (isset($permalink_manager_options[$section_name][$field_name])) ? $permalink_manager_options[$section_name][$field_name] : $default;
205 } else {
206 $value = (isset($permalink_manager_options[$input_name])) ? $permalink_manager_options[$input_name] : $default;
207 }
208 }
209
210 switch($field_type) {
211 case 'checkbox' :
212 $fields .= '<div class="checkboxes">';
213 foreach($args['choices'] as $choice_value => $choice) {
214 $input_template = "<label for='%s[]'><input type='checkbox' %s value='%s' name='%s[]' %s /> %s</label>";
215
216 if(empty($choice['label']) && is_array($choice)) {
217 foreach($choice as $sub_choice_value => $sub_choice) {
218 $label = (!empty($sub_choice['label'])) ? $sub_choice['label'] : $sub_choice;
219 $atts = (!empty($value[$choice_value]) && in_array($sub_choice_value, $value[$choice_value])) ? "checked='checked'" : "";
220 $atts .= (!empty($sub_choice['atts'])) ? " {$sub_choice['atts']}" : "";
221
222 $fields .= sprintf($input_template, $input_name, $input_atts, $sub_choice_value, "{$input_name}[{$choice_value}]", $atts, $label);
223 }
224 } else {
225 $label = (!empty($choice['label'])) ? $choice['label'] : $choice;
226 $atts = (is_array($value) && in_array($choice_value, $value)) ? "checked='checked'" : "";
227 $atts .= (!empty($choice['atts'])) ? " {$choice['atts']}" : "";
228
229 $fields .= sprintf($input_template, $input_name, $input_atts, $choice_value, $input_name, $atts, $label);
230 }
231 }
232 $fields .= '</div>';
233
234 // Add helper checkboxes for bulk actions
235 if(isset($args['select_all']) || isset($args['unselect_all'])) {
236 $select_all_label = (!empty($args['select_all'])) ? $args['select_all'] : __('Select all', 'permalink-manager');
237 $unselect_all_label = (!empty($args['unselect_all'])) ? $args['unselect_all'] : __('Unselect all', 'permalink-manager');
238
239 $fields .= "<p class=\"checkbox_actions extra-links\">";
240 $fields .= (isset($args['select_all'])) ? "<a href=\"#\" class=\"select_all\">{$select_all_label}</a>&nbsp;" : "";
241 $fields .= (isset($args['unselect_all'])) ? "<a href=\"#\" class=\"unselect_all\">{$unselect_all_label}</a>" : "";
242 $fields .= "</p>";
243 }
244 break;
245
246 case 'single_checkbox' :
247 $fields .= '<div class="single_checkbox">';
248 $checked = ($value == 1) ? "checked='checked'" : "";
249 $checkbox_label = (isset($args['checkbox_label'])) ? $args['checkbox_label'] : '';
250
251 $fields .= "<input type='hidden' {$input_atts} value='0' name='{$input_name}' />";
252 $fields .= "<label for='{$input_name}'><input type='checkbox' {$input_atts} value='1' name='{$input_name}' {$checked} /> {$checkbox_label}</label>";
253 $fields .= '</div>';
254 break;
255
256 case 'radio' :
257 $fields .= '<div class="radios">';
258 foreach($args['choices'] as $choice_value => $choice) {
259 $label = (is_array($choice)) ? $choice['label'] : $choice;
260 $atts = ($choice_value == $value) ? "checked='checked'" : "";
261 $atts .= (!empty($choice['atts'])) ? " {$choice['atts']}" : "";
262
263 $fields .= "<label for='{$input_name}[]'><input type='radio' {$input_atts} value='{$choice_value}' name='{$input_name}[]' {$atts} /> {$label}</label>";
264 }
265 $fields .= '</div>';
266 break;
267
268 case 'select' :
269 $fields .= '<span class="select">';
270 $fields .= "<select name='{$input_name}' {$input_atts}>";
271 foreach($args['choices'] as $choice_value => $choice) {
272 $label = (is_array($choice)) ? $choice['label'] : $choice;
273 $atts = ($choice_value == $value) ? "selected='selected'" : "";
274 $atts .= (!empty($choice['atts'])) ? " {$choice['atts']}" : "";
275
276 $fields .= "<option value='{$choice_value}' {$atts}>{$label}</option>";
277 }
278 $fields .= '</select>';
279 $fields .= '</span>';
280 break;
281
282 case 'number' :
283 $fields .= "<input type='number' {$input_atts} value='{$value}' name='{$input_name}' />";
284 break;
285
286 case 'hidden' :
287 $fields .= "<input type='hidden' {$input_atts} value='{$value}' name='{$input_name}' />";
288 break;
289
290 case 'textarea' :
291 $fields .= "<textarea {$input_atts} name='{$input_name}' {$rows}>{$value}</textarea>";
292 break;
293
294 case 'pre' :
295 $fields .= "<pre {$input_atts}>{$value}</pre>";
296 break;
297
298 case 'info' :
299 $fields .= "<div {$input_atts}>{$value}</div>";
300 break;
301
302 case 'clearfix' :
303 return "<div class=\"clearfix\"></div>";
304
305 case 'permastruct' :
306 $siteurl = Permalink_Manager_Helper_Functions::get_permalink_base();
307
308 if(!empty($args['post_type'])) {
309 $type = $args['post_type'];
310 $type_name = $type['name'];
311
312 $permastructures = (!empty($permalink_manager_permastructs['post_types'])) ? $permalink_manager_permastructs['post_types'] : array();
313 } else if(!empty($args['taxonomy'])) {
314 $type = $args['taxonomy'];
315 $type_name = $type['name'];
316
317 $permastructures = (!empty($permalink_manager_permastructs['taxonomies'])) ? $permalink_manager_permastructs['taxonomies'] : array();
318 } else {
319 break;
320 }
321
322 // Get permastructures
323 $default_permastruct = trim(Permalink_Manager_Helper_Functions::get_default_permastruct($type_name), "/");
324 $current_permastruct = isset($permastructures[$type_name]) ? $permastructures[$type_name] : $default_permastruct;
325
326 // Append extra attributes
327 $input_atts .= " data-default=\"{$default_permastruct}\"";
328 $input_atts .= " placeholder=\"{$default_permastruct}\"";
329
330 $fields .= "<div class=\"all-permastruct-container\">";
331
332 // 1. Default permastructure
333 $fields .= "<div class=\"permastruct-container\">";
334 $fields .= "<span><code>{$siteurl}/</code></span>";
335 $fields .= "<span><input type='text' {$input_atts} value='{$current_permastruct}' name='{$input_name}'/></span>";
336 $fields .= "</div>";
337
338 $fields .= "<div class=\"permastruct-toggle\">";
339
340 // 2A. Permastructure for each language
341 $languages = (array) Permalink_Manager_Third_Parties::get_all_languages(true);
342 if($languages) {
343 $fields .= sprintf(
344 "<h4>%s</h4><p class=\"permastruct-instruction\">%s</p>",
345 __("Permastructure translations", "permalink-manager"),
346 __("If you would like to translate the permastructures and set-up different permalink structure per language, please fill in the fields below. Otherwise the permastructure set for default language (see field above) will be applied.", "permalink-manager")
347 );
348
349 foreach($languages as $lang => $name) {
350 $current_lang_permastruct = isset($permastructures["{$type_name}_{$lang}"]) ? $permastructures["{$type_name}_{$lang}"] : '';
351
352 $fields .= "<label>{$name}</label>";
353 $fields .= "<div class=\"permastruct-container\">";
354 $fields .= "<span><code>{$siteurl}/</code></span>";
355 $fields .= sprintf("<span><input type='text' %s value='%s' name='%s'/></span>", $input_atts, $current_lang_permastruct, str_replace("]", "_{$lang}]", $input_name));
356 $fields .= "</div>";
357 }
358 }
359
360 // 2B. Restore default permalinks
361 $fields .= sprintf(
362 "<p class=\"default-permastruct-row columns-container\"><span class=\"column-2_4\"><strong>%s:</strong> %s</span><span class=\"column-2_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></p>",
363 __("Default permastructure", "permalink-manager"), esc_html($default_permastruct),
364 __("Restore default permastructure", "permalink-manager")
365 );
366 $fields .= "</div>";
367
368 // 3. Show toggle button
369 $fields .= sprintf(
370 "<p class=\"permastruct-toggle-button\"><a href=\"#\"><span class=\"dashicons dashicons-admin-settings\"></span> %s</a></p>",
371 __("Show additional settings", "permalink-manager")
372 );
373
374 $fields .= "</div>";
375
376 break;
377
378 default :
379 $fields .= "<input type='text' {$input_atts} value='{$value}' name='{$input_name}'/>";
380 }
381
382 // Get the final HTML output
383 if(isset($args['container']) && $args['container'] == 'tools') {
384 $html = "<div{$container_class}>";
385 $html .= "<h4>{$label}</h4>";
386 $html .= "<div class='{$input_name}-container'>{$fields}</div>";
387 $html .= $description;
388 $html .= $append_content;
389 $html .= "</div>";
390 } else if(isset($args['container']) && $args['container'] == 'row') {
391 $html = "<tr data-field=\"{$input_name}\" {$container_class}><th><label for='{$input_name}'>{$args['label']}</label></th>";
392 $html .= "<td><fieldset>{$fields}{$description}</fieldset></td></tr>";
393 $html .= ($append_content) ? "<tr class=\"appended-row\"><td colspan=\"2\">{$append_content}</td></tr>" : "";
394 } else if(isset($args['container']) && $args['container'] == 'screen-options') {
395 $html = "<fieldset data-field=\"{$input_name}\" {$container_class}><legend>{$args['label']}</legend>";
396 $html .= "<div class=\"field-content\">{$fields}{$description}</div>";
397 $html .= ($append_content) ? "<div class=\"appended-row\">{$append_content}</div>" : "";
398 $html .= "</fieldset>";
399 } else {
400 $html = $fields . $append_content;
401 }
402
403 return apply_filters('permalink_manager_field_output', $html);
404 }
405
406 /**
407 * Display hidden field to indicate posts or taxonomies admin sections
408 */
409 static public function section_type_field($type = 'post') {
410 return self::generate_option_field('content_type', array('value' => $type, 'type' => 'hidden'));
411 }
412
413 /**
414 * Display the form
415 */
416 static public function get_the_form($fields = array(), $container = '', $button = array(), $sidebar = '', $nonce = array(), $wrap = false, $form_class = '') {
417 // 1. Check if the content will be displayed in columns and button details
418 switch($container) {
419 case 'columns-3' :
420 $wrapper_class = 'columns-container';
421 $form_column_class = 'column column-2_3';
422 $sidebar_class = 'column column-1_3';
423 break;
424
425 // there will be more cases in future ...
426 default :
427 $form_column_class = 'form';
428 $sidebar_class = 'sidebar';
429 $wrapper_class = $form_column_class = '';
430 }
431
432 // 2. Process the array with button and nonce field settings
433 $button_text = (!empty($button['text'])) ? $button['text'] : '';
434 $button_class = (!empty($button['class'])) ? $button['class'] : '';
435 $button_attributes = (!empty($button['attributes'])) ? $button['attributes'] : '';
436 $nonce_action = (!empty($nonce['action'])) ? $nonce['action'] : '';
437 $nonce_name = (!empty($nonce['name'])) ? $nonce['name'] : '';
438 $form_classes = (!empty($form_class)) ? $form_class : '';
439
440 // 2. Now get the HTML output (start section row container)
441 $html = ($wrapper_class) ? "<div class=\"{$wrapper_class}\">" : '';
442
443 // 3. Display some notes
444 if($sidebar_class && $sidebar) {
445 $html .= "<div class=\"{$sidebar_class}\">";
446 $html .= "<div class=\"section-notes\">";
447 $html .= $sidebar;
448 $html .= "</div>";
449 $html .= "</div>";
450 }
451
452 // 4. Start fields' section
453 $html .= ($form_column_class) ? "<div class=\"{$form_column_class}\">" : "";
454 $html .= "<form method=\"POST\" class=\"{$form_classes}\">";
455 $html .= ($wrap) ? "<table class=\"form-table\">" : "";
456
457 // Loop through all fields assigned to this section
458 foreach($fields as $field_name => $field) {
459 $field_name = (!empty($field['name'])) ? $field['name'] : $field_name;
460
461 // A. Display table row
462 if(isset($field['container']) && $field['container'] == 'row') {
463 $row_output = "";
464
465 // Loop through all fields assigned to this section
466 if(isset($field['fields'])) {
467 foreach($field['fields'] as $section_field_id => $section_field) {
468 $section_field_name = (!empty($section_field['name'])) ? $section_field['name'] : "{$field_name}[$section_field_id]";
469 $section_field['container'] = 'row';
470
471 $row_output .= self::generate_option_field($section_field_name, $section_field);
472 }
473 } else {
474 $row_output .= self::generate_option_field($field_name, $field);
475 }
476
477 if(isset($field['section_name'])) {
478 $html .= "<h3>{$field['section_name']}</h3>";
479 $html .= (isset($field['append_content'])) ? $field['append_content'] : "";
480 $html .= (isset($field['description'])) ? "<p class=\"description\">{$field['description']}</p>" : "";
481 $html .= "<table class=\"form-table\" data-field=\"{$field_name}\">{$row_output}</table>";
482 } else {
483 $html .= $row_output;
484 }
485 }
486 // B. Display single field
487 else {
488 $html .= self::generate_option_field($field_name, $field);
489 }
490 }
491
492 $html .= ($wrap) ? "</table>" : "";
493
494 // End the fields' section + add button & nonce fields
495 if($nonce_action && $nonce_name) {
496 $html .= wp_nonce_field($nonce_action, $nonce_name, true, true);
497 $html .= self::generate_option_field('pm_session_id', array('value' => uniqid(), 'type' => 'hidden'));
498 }
499 $html .= ($button_text) ? get_submit_button($button_text, $button_class, '', false, $button_attributes) : "";
500 $html .= '</form>';
501 $html .= ($form_column_class) ? "</div>" : "";
502
503 // 5. End the section row container
504 $html .= ($wrapper_class) ? "</div>" : "";
505
506 return $html;
507 }
508
509 /**
510 * Display the plugin sections.
511 */
512 public function display_section() {
513 global $wpdb, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
514
515 $html = "<div id=\"permalink-manager\" class=\"wrap\">";
516
517 $donate_link = defined('PERMALINK_MANAGER_PRO') ? "" : sprintf("<a href=\"%s\" target=\"_blank\" class=\"page-title-action\">%s</a>", PERMALINK_MANAGER_DONATE, __("Donate", "permalink-manager"));
518 $html .= sprintf("<h2 id=\"plugin-name-heading\">%s <a href=\"http://maciejbis.net\" class=\"author-link\" target=\"_blank\">%s</a> %s</h2>", PERMALINK_MANAGER_PLUGIN_NAME, __("by Maciej Bis", "permalink-manager"), $donate_link);
519
520 // Display the tab navigation
521 $html .= "<div id=\"permalink-manager-tab-nav\" class=\"nav-tab-wrapper\">";
522 foreach($this->sections as $section_name => $section_properties) {
523 $active_class = ($this->active_section === $section_name) ? 'nav-tab-active nav-tab' : 'nav-tab';
524 $section_url = $this->get_admin_url("&section={$section_name}");
525
526 $html .= "<a href=\"{$section_url}\" class=\"{$active_class} section_{$section_name}\">{$section_properties['name']}</a>";
527 }
528 $html .= "</div>";
529
530 // Now display the active section
531 $html .= "<div id=\"permalink-manager-sections\">";
532 $active_section_array = (isset($this->sections[$this->active_section])) ? $this->sections[$this->active_section] : "";
533
534 // Display addidional navigation for subsections
535 if(isset($this->sections[$this->active_section]['subsections'])) {
536 $html .= "<ul class=\"subsubsub\">";
537 foreach ($this->sections[$this->active_section]['subsections'] as $subsection_name => $subsection) {
538 $active_class = ($this->active_subsection === $subsection_name) ? 'current' : '';
539 $subsection_url = $this->get_admin_url("&section={$this->active_section}&subsection={$subsection_name}");
540
541 $html .= "<li><a href=\"{$subsection_url}\" class=\"{$active_class}\">{$subsection['name']}</a></li>";
542 }
543 $html .= "</ul>";
544 }
545
546 // A. Execute the function assigned to the subsection
547 if(isset($active_section_array['subsections'][$this->active_subsection]['function'])) {
548 $class_name = $active_section_array['subsections'][$this->active_subsection]['function']['class'];
549 $section_object = new $class_name();
550
551 $section_content = call_user_func(array($section_object, $active_section_array['subsections'][$this->active_subsection]['function']['method']));
552 }
553 // B. Execute the function assigned to the section
554 else if(isset($active_section_array['function'])) {
555 $class_name = $active_section_array['function']['class'];
556 $section_object = new $class_name();
557
558 $section_content = call_user_func(array($section_object, $active_section_array['function']['method']));
559 }
560 // C. Display the raw HTMl output of subsection
561 else if(isset($active_section_array['subsections'][$this->active_subsection]['html'])) {
562 $section_content = (isset($active_section_array['subsections'][$this->active_subsection]['html'])) ? $active_section_array['subsections'][$this->active_subsection]['html'] : "";
563 }
564 // D. Try to display the raw HTMl output of section
565 else {
566 $section_content = (isset($active_section_array['html'])) ? $active_section_array['html'] : "";
567 }
568
569 $html .= "<div class=\"single-section\" data-section=\"{$this->active_section}\" id=\"{$this->active_section}\">{$section_content}</div>";
570 $html .= "</div>";
571
572 // Display alerts and another content if needed and close .wrap container
573 $html .= $permalink_manager_after_sections_html;
574 $html .= "</div>";
575
576 echo $html;
577 }
578
579 /**
580 * Display the table with updated slugs after one of the actions is triggered
581 */
582 static function display_updated_slugs($updated_array, $return_array = false, $display_full_table = true) {
583 global $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
584
585 $updated_slugs_count = 0;
586 $html = $main_content = $alert = "";
587
588 if(is_array($updated_array)) {
589 // Check if slugs should be displayed
590 $first_slug = reset($updated_array);
591
592 $header_footer = '<tr>';
593 $header_footer .= '<th class="column-primary">' . __('Title', 'permalink-manager') . '</th>';
594 $header_footer .= '<th>' . __('Old URI', 'permalink-manager') . '</th>';
595 $header_footer .= '<th>' . __('New URI', 'permalink-manager') . '</th>';
596 $header_footer .= (isset($first_slug['old_slug'])) ? '<th>' . __('Old Slug', 'permalink-manager') . '</th>' : "";
597 $header_footer .= (isset($first_slug['new_slug'])) ? '<th>' . __('New Slug', 'permalink-manager') . '</th>' : "";
598 $header_footer .= '</tr>';
599
600 foreach($updated_array as $row) {
601 // Odd/even class
602 $updated_slugs_count++;
603 $alternate_class = ($updated_slugs_count % 2 == 1) ? ' class="alternate"' : '';
604
605 // Taxonomy
606 if(!empty($row['tax'])) {
607 $term_link = get_term_link(intval($row['ID']), $row['tax']);
608 $permalink = (is_wp_error($term_link)) ? "-" : $term_link;
609 } else {
610 $permalink = get_permalink($row['ID']);
611 }
612
613 // Decode permalink
614 $permalink = urldecode(urldecode($permalink));
615
616 $main_content .= "<tr{$alternate_class}>";
617 $main_content .= '<td class="row-title column-primary" data-colname="' . __('Title', 'permalink-manager') . '">' . $row['item_title'] . "<a target=\"_blank\" href=\"{$permalink}\"><span class=\"small\">{$permalink}</span></a>" . '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __('Show more details', 'permalink-manager') . '</span></button></td>';
618 $main_content .= '<td data-colname="' . __('Old URI', 'permalink-manager') . '">' . urldecode($row['old_uri']) . '</td>';
619 $main_content .= '<td data-colname="' . __('New URI', 'permalink-manager') . '">' . urldecode($row['new_uri']) . '</td>';
620 $main_content .= (isset($row['old_slug'])) ? '<td data-colname="' . __('Old Slug', 'permalink-manager') . '">' . urldecode($row['old_slug']) . '</td>' : "";
621 $main_content .= (isset($row['new_slug'])) ? '<td data-colname="' . __('New Slug', 'permalink-manager') . '">' . urldecode($row['new_slug']) . '</td>' : "";
622 $main_content .= '</tr>';
623 }
624
625 // Merge header, footer and content
626 if($display_full_table) {
627 $html = '<h3 id="updated-list">' . __('List of updated items', 'permalink-manager') . '</h3>';
628 $html .= '<table class="widefat wp-list-table updated-slugs-table">';
629 $html .= "<thead>{$header_footer}</thead><tbody>{$main_content}</tbody><tfoot>{$header_footer}</tfoot>";
630 } else {
631 $html = $main_content;
632 }
633
634 $html .= '</table>';
635 }
636
637 // 3. Display the alert
638 if(isset($updated_slugs_count)) {
639 if($updated_slugs_count > 0) {
640 $alert_content = sprintf( _n( '<strong class="updated_count">%d</strong> slug was updated!', '<strong class="updated_count">%d</strong> slugs were updated!', $updated_slugs_count, 'permalink-manager' ), $updated_slugs_count ) . ' ';
641 $alert_content .= sprintf( __( '<a %s>Click here</a> to go to the list of updated slugs', 'permalink-manager' ), "href=\"#updated-list\"");
642
643 $alert = Permalink_Manager_Admin_Functions::get_alert_message($alert_content, 'updated updated_slugs');
644 } else {
645 $alert = Permalink_Manager_Admin_Functions::get_alert_message(__( '<strong>No slugs</strong> were updated!', 'permalink-manager' ), 'error updated_slugs');
646 }
647 }
648
649 if($return_array) {
650 return array(
651 'html' => $html,
652 'alert' => $alert
653 );
654 } else {
655 $permalink_manager_before_sections_html .= $alert;
656
657 return $html;
658 }
659 }
660
661 /**
662 * "Quick Edit" Box
663 */
664 public static function quick_edit_column_form($is_taxonomy = false) {
665 $html = self::generate_option_field('permalink-manager-quick-edit', array('value' => true, 'type' => 'hidden'));
666 $html .= "<fieldset class=\"inline-edit-permalink\">";
667 $html .= sprintf("<legend class=\"inline-edit-legend\">%s</legend>", __("Permalink Manager", "permalink-manager"));
668
669 $html .= "<div class=\"inline-edit-col\">";
670 $html .= sprintf("<label class=\"inline-edit-group\"><span class=\"title\">%s</span><span class=\"input-text-wrap\">%s</span></label>",
671 __("Current URI", "permalink-manager"),
672 self::generate_option_field("custom_uri", array("input_class" => "custom_uri", "value" => ''))
673 );
674 $html .= "</div>";
675
676 $html .= "</fieldset>";
677
678 // Append nonce field & element ID
679 $html .= Permalink_Manager_Admin_Functions::generate_option_field("permalink-manager-edit-uri-element-id", array("type" => "hidden", "input_class" => "permalink-manager-edit-uri-element-id", "value" => ""));
680 $html .= wp_nonce_field( 'permalink-manager-edit-uri-box', 'permalink-manager-nonce', true, false );
681
682 return $html;
683 }
684
685 /**
686 * Hide "Custom URI" column
687 */
688 function quick_edit_hide_column($hidden, $screen) {
689 $hidden[] = 'permalink-manager-col';
690 return $hidden;
691 }
692
693 /**
694 * Display "Permalink Manager" box
695 */
696 public static function display_uri_box($element, $gutenberg = false) {
697 global $permalink_manager_options, $permalink_manager_uris;
698
699 if(!empty($element->ID)) {
700 $id = $element_id = $element->ID;
701 $native_slug = $element->post_name;
702 $is_draft = (!empty($element->post_status) && (in_array($element->post_status, array('draft', 'auto-draft')))) ? true : false;
703 $is_front_page = Permalink_Manager_Helper_Functions::is_front_page($id);
704
705 // Auto-update settings
706 $auto_update_val = get_post_meta($id, "auto_update_uri", true);
707 $auto_update_def_val = $permalink_manager_options["general"]["auto_update_uris"];
708 $auto_update_def_label = ($auto_update_def_val) ? __("Yes", "permalink-manager") : __("No", "permalink-manager");
709 $auto_update_choices = array(
710 0 => array("label" => sprintf(__("Use global settings [%s]", "permalink-manager"), $auto_update_def_label), "atts" => "data-auto-update=\"{$auto_update_def_val}\""),
711 -1 => array("label" => __("No", "permalink-manager"), "atts" => "data-auto-update=\"0\""),
712 1 => array("label" => __("Yes", "permalink-manager"), "atts" => "data-auto-update=\"1\"")
713 );
714
715 // Get URIs
716 $uri = Permalink_Manager_URI_Functions_Post::get_post_uri($id, true, $is_draft);
717 $default_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($id);
718 $native_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri($id, true);
719 } else if(class_exists('Permalink_Manager_URI_Functions_Tax')) {
720 $id = $element->term_id;
721 $element_id = "tax-{$id}";
722 $native_slug = $element->slug;
723
724 // Get URIs
725 $uri = Permalink_Manager_URI_Functions_Tax::get_term_uri($element->term_id, true);
726 $default_uri = Permalink_Manager_URI_Functions_Tax::get_default_term_uri($element->term_id);
727 $native_uri = Permalink_Manager_URI_Functions_Tax::get_default_term_uri($element->term_id, true);
728 } else {
729 return;
730 }
731
732 // Decode default URI
733 $default_uri = urldecode($default_uri);
734
735 // Start HTML output
736 // 1. Button
737 if(!$gutenberg) {
738 $html = sprintf("<span><button type=\"button\" class=\"button button-small hide-if-no-js\" id=\"permalink-manager-toggle\">%s</button></span>", __("Permalink Manager", "permalink-manager"));
739
740 $html .= "<div id=\"permalink-manager\" class=\"postbox permalink-manager-edit-uri-box\" style=\"display: none;\">";
741
742 // 2. The heading
743 $html .= "<a class=\"close-button\"><span class=\"screen-reader-text\">" . __("Close: ", "permalink-manager") . __("Permalink Manager", "permalink-manager") . "</span><span class=\"close-icon\" aria-hidden=\"false\"></span></a>";
744 $html .= sprintf("<h2><span>%s</span></h2>", __("Permalink Manager", "permalink-manager"));
745
746 // 3. The fields container [start]
747 $html .= "<div class=\"inside\">";
748 } else {
749 $html = "<div class=\"permalink-manager-gutenberg permalink-manager-edit-uri-box\">";
750 }
751
752 // 4. Custom URI
753 if(!empty($is_front_page)) {
754 $custom_uri_field = Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("type" => "hidden", "extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => rawurldecode($uri)));
755 $custom_uri_field .= __("The custom URI cannot be edited on frontpage.", "permalink-manager");
756 } else {
757 $custom_uri_field = Permalink_Manager_Admin_Functions::generate_option_field("custom_uri", array("extra_atts" => "data-default=\"{$default_uri}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat custom_uri", "value" => rawurldecode($uri)));
758 }
759
760 $html .= sprintf("<div class=\"custom_uri_container\"><p><label for=\"custom_uri\" class=\"strong\">%s %s</label></p><span>%s</span><span class=\"duplicated_uri_alert\"></span></div>",
761 __("Current URI", "permalink-manager"),
762 ($element->ID) ? Permalink_Manager_Admin_Functions::help_tooltip(__("If custom URI is not defined, a default URI will be set (see below). The custom URI can be edited only if 'Auto-update the URI' feature is not enabled.", "permalink-manager")) : "",
763 $custom_uri_field
764 );
765
766 // 5. Native slug
767 if(!empty($element->ID) && !empty($permalink_manager_options["general"]["show_native_slug_field"])) {
768 $native_slug_field = Permalink_Manager_Admin_Functions::generate_option_field("native_slug", array("extra_atts" => "data-default=\"{$native_slug}\" data-element-id=\"{$element_id}\"", "input_class" => "widefat native_slug", "value" => urldecode($native_slug)));
769
770 $html .= sprintf("<div class=\"native_slug_container\"><p><label for=\"native_slug\" class=\"strong\">%s %s</label></p><span>%s</span></div>",
771 __("Native slug", "permalink-manager"),
772 Permalink_Manager_Admin_Functions::help_tooltip(__("The native slug is by default automatically used in native permalinks (when Permalink Manager is disabled).", "permalink-manager")),
773 $native_slug_field
774 );
775 }
776
777 // Three fields that should be hidden on front-page
778 if(empty($is_front_page)) {
779 // 6. Auto-update URI
780 if(!empty($auto_update_choices)) {
781 $html .= sprintf("<div><p><label for=\"auto_auri\" class=\"strong\">%s %s</label></p><span>%s</span></div>",
782 __("Auto-update the URI", "permalink-manager"),
783 Permalink_Manager_Admin_Functions::help_tooltip(__("If enabled, the 'Current URI' field will be automatically changed to 'Default URI' (displayed below) after the post is saved or updated.", "permalink-manager")),
784 Permalink_Manager_Admin_Functions::generate_option_field("auto_update_uri", array("type" => "select", "input_class" => "widefat auto_update", "value" => $auto_update_val, "choices" => $auto_update_choices))
785 );
786 }
787
788 // 7. Default URI
789 $html .= sprintf(
790 "<div class=\"default-permalink-row columns-container\"><span class=\"column-3_4\"><strong>%s:</strong> %s</span><span class=\"column-1_4\"><a href=\"#\" class=\"restore-default\"><span class=\"dashicons dashicons-image-rotate\"></span> %s</a></span></div>",
791 __("Default URI", "permalink-manager"), esc_html($default_uri),
792 __("Restore Default URI", "permalink-manager")
793 );
794
795 // 8. Native URI info
796 if(!empty($permalink_manager_options['general']['redirect']) && ((!empty($element->post_status) && in_array($element->post_status, array('auto-draft', 'trash', 'draft'))) == false)) {
797 $native_permalink = trim(Permalink_Manager_Helper_Functions::get_permalink_base($element), "/") . "/";
798 $native_permalink .= $native_uri;
799
800 $html .= sprintf(
801 "<div class=\"default-permalink-row columns-container\"><span><strong>%s</strong> <a href=\"%s\">%s</a></span></div>",
802 __("Automatic redirect for native URI enabled:", "permalink-manager"),
803 $native_permalink,
804 urldecode($native_uri)
805 );
806 }
807 }
808
809 // 9. Custom redirects
810 $html .= ($element->ID) ? self::display_redirect_panel($id) : self::display_redirect_panel("tax-{$id}");
811
812 // 10. Extra save button for Gutenberg
813 if($gutenberg) {
814 $html .= sprintf(
815 "<div class=\"default-permalink-row save-row columns-container hidden\"><div><a href=\"#\" class=\"button button-primary\" id=\"permalink-manager-save-button\">%s</a></div></div>",
816 __("Save permalink", "permalink-manager")
817 );
818 }
819
820 $html .= "</div>";
821 $html .= "</div>";
822
823 // 11. Append nonce field, element ID & native slug
824 $html .= Permalink_Manager_Admin_Functions::generate_option_field("permalink-manager-edit-uri-element-slug", array("type" => "hidden", "value" => $native_slug));
825 $html .= Permalink_Manager_Admin_Functions::generate_option_field("permalink-manager-edit-uri-element-id", array("type" => "hidden", "value" => $element_id));
826 $html .= wp_nonce_field('permalink-manager-edit-uri-box', 'permalink-manager-nonce', true, false);
827
828 return $html;
829 }
830
831 /**
832 * Display the redirect panel
833 */
834 public static function display_redirect_panel($element_id) {
835 global $permalink_manager_options, $permalink_manager_redirects;
836
837 // Heading
838 $html = sprintf(
839 "<div class=\"permalink-manager redirects-row redirects-panel columns-container\"><div><a class=\"button\" href=\"#\" id=\"toggle-redirect-panel\">%s</a></span></div>",
840 __("Manage redirects", "permalink-manager")
841 );
842
843 $html .= "<div id=\"redirect-panel-inside\">";
844
845 // Table
846 if(Permalink_Manager_Admin_Functions::is_pro_active()) {
847 $html .= Permalink_Manager_Pro_Addons::display_redirect_form($element_id);
848 } else {
849 $html .= self::pro_text(true);
850 }
851
852 $html .= "</div></div>";
853
854 return $html;
855 }
856
857 /**
858 * Display error/info message
859 */
860 public static function get_alert_message($alert_content = "", $alert_type = "", $dismissable = true, $id = false) {
861 // Ignore empty messages (just in case)
862 if(empty($alert_content) || empty($alert_type)) {
863 return "";
864 }
865
866 $class = ($dismissable) ? "is-dismissible" : "";
867 $alert_id = ($id) ? " data-alert_id=\"{$id}\"" : "";
868
869 $html = sprintf( "<div class=\"{$alert_type} permalink-manager-notice notice {$class}\"{$alert_id}> %s</div>", wpautop($alert_content) );
870
871 return $html;
872 }
873
874 /**
875 * Help tooltip
876 */
877 static function help_tooltip($text = '') {
878 $html = " <a href=\"#\" title=\"{$text}\" class=\"help_tooltip\"><span class=\"dashicons dashicons-editor-help\"></span></a>";
879 return $html;
880 }
881
882 /**
883 * Display global notices (throughout wp-admin dashboard)
884 */
885 function display_global_notices() {
886 global $permalink_manager_alerts, $active_section;
887
888 $html = "";
889 if(!empty($permalink_manager_alerts) && is_array($permalink_manager_alerts)) {
890 foreach($permalink_manager_alerts as $alert_id => $alert) {
891 if(!empty($alert['show'])) {
892 // Hide notice in Permalink Manager Pro
893 if(defined('PERMALINK_MANAGER_PRO') && $alert['show'] == 'pro_hide') { continue; }
894
895 // Display the notice only on the plugin pages
896 if(empty($active_section) && !empty($alert['plugin_only'])) { continue; }
897
898 // Check if the notice did not expire
899 if(isset($alert['until']) && (time() > strtotime($alert['until']))) { continue; }
900
901 $html .= self::get_alert_message($alert['txt'], $alert['type'], true, $alert_id);
902 }
903 }
904 }
905
906 echo $html;
907 }
908
909 /**
910 * Hide global notices (AJAX)
911 */
912 function hide_global_notice() {
913 global $permalink_manager_alerts;
914
915 // Get the ID of the alert
916 $alert_id = (!empty($_REQUEST['alert_id'])) ? sanitize_title($_REQUEST['alert_id']) : "";
917 if(!empty($permalink_manager_alerts[$alert_id])) {
918 $permalink_manager_alerts[$alert_id]['show'] = 0;
919 }
920
921 update_option( 'permalink-manager-alerts', $permalink_manager_alerts);
922 }
923
924 /**
925 * Display notices generated by Permalink Manager tools
926 */
927 function display_plugin_notices() {
928 global $permalink_manager_before_sections_html;
929
930 echo $permalink_manager_before_sections_html;
931 }
932
933 /**
934 * Check if URI was used before
935 */
936 function ajax_detect_duplicates($uri = null, $element_id = null) {
937 $duplicate_alert = __("URI is already in use, please select another one!", "permalink-manager");
938
939 if(!empty($_REQUEST['custom_uris'])) {
940 // Sanitize the array
941 $custom_uris = Permalink_Manager_Helper_Functions::sanitize_array($_REQUEST['custom_uris']);
942 $duplicates_array = array();
943
944 // Check each URI
945 foreach($custom_uris as $element_id => $uri) {
946 $duplicates_array[$element_id] = Permalink_Manager_Helper_Functions::is_uri_duplicated($uri, $element_id) ? $duplicate_alert : 0;
947 }
948
949 // Convert the output to JSON and stop the function
950 echo json_encode($duplicates_array);
951 } else if(!empty($_REQUEST['custom_uri']) && !empty($_REQUEST['element_id'])) {
952 $is_duplicated = Permalink_Manager_Helper_Functions::is_uri_duplicated($uri, $element_id);
953
954 echo ($is_duplicated) ? $duplicate_alert : 0;;
955 }
956
957 die();
958 }
959
960 /**
961 * Check if Permalink Manager Pro is active
962 */
963 public static function is_pro_active($return_text = false) {
964 if(defined('PERMALINK_MANAGER_PRO') && PERMALINK_MANAGER_PRO == true) {
965 $is_pro = true;
966 } else {
967 $is_pro = false;
968 }
969
970 // Check if license is active
971 if(class_exists('Permalink_Manager_Pro_Functions')) {
972 $exp_date = Permalink_Manager_Pro_Functions::get_expiration_date(true);
973
974 $is_pro = ($exp_date > 0) ? false : true;
975 } else {
976 $is_pro = false;
977 }
978
979 return $is_pro;
980 }
981
982 static function pro_text($text_only = false) {
983 if(class_exists('Permalink_Manager_Pro_Functions')) {
984 $text = Permalink_Manager_Pro_Functions::get_expiration_date(false, true);
985 } else {
986 $text = sprintf(__('This functionality is available only in <a href="%s" target="_blank">Permalink Manager Pro</a>.', 'permalink-manager'), PERMALINK_MANAGER_WEBSITE);
987 }
988
989 return ($text_only) ? $text : sprintf("<div class=\"alert info\"> %s</div>", wpautop($text, 'alert', false));
990 }
991
992 }
993