'Version'), 'plugin');
self::$version = $plugin_data['version'];
self::$plugin_url = plugins_url('', __FILE__) . '/';
} // init
// add settings link to plugins page
static function plugin_action_links($links)
{
$settings_link = 'Manage Redirects ';
$pro_link = 'Get PRO ';
array_unshift($links, $pro_link);
array_unshift($links, $settings_link);
return $links;
} // plugin_action_links
static function load_301_redirect_assets($adminpage)
{
if ($adminpage != 'settings_page_301-redirects') {
return;
}
wp_enqueue_style('redirect_301_bootstrap_css', plugin_dir_url(__FILE__) . 'css/bootstrap.min.css', false, self::$version);
wp_enqueue_style('redirect_301_custom_css', plugin_dir_url(__FILE__) . 'css/style.css', false, self::$version);
wp_enqueue_script('redirect_301_bootstrap', plugin_dir_url(__FILE__) . 'js/bootstrap.min.js', true, self::$version);
wp_enqueue_script('redirect_301_custom_js', plugin_dir_url(__FILE__) . 'js/ts-redirects.js', true, self::$version);
wp_enqueue_style('wp-jquery-ui-dialog');
wp_enqueue_script('jquery-ui-dialog');
$options = get_option('ts_301_redirection', array());
$js_localize = array(
'nonce_delete_rule' => wp_create_nonce('redirect_delete_rule'),
'auto_open_pro_dialog' => empty($options['dismiss_auto_pro_modal']),
);
wp_localize_script('redirect_301_custom_js', 'redirect', $js_localize);
$options['dismiss_auto_pro_modal'] = true;
update_option('ts_301_redirection', $options);
} //load_301_redirect_assets
// additional powered by text in admin footer; only on 301 page
static function admin_footer_text($text)
{
if (!self::is_plugin_page()) {
return $text;
}
$text = 'WP 301 Redirects v' . self::$version . ' by WebFactory Ltd . Please rate the plugin ★★★★★ to help us spread the word. Thank you! ';
return $text;
} // admin_footer_text
// test if we're on plugin's page
static function is_plugin_page()
{
$current_screen = get_current_screen();
if ($current_screen->id == 'settings_page_301-redirects') {
return true;
} else {
return false;
}
} // is_plugin_page
static function check_404()
{
if (!is_404()) {
return;
}
$log404 = get_option('301_redirects_404_log', array());
if (!is_array($log404)) {
$log404 = array();
}
$ua = \tsdonatj\UserAgent\parse_user_agent(wp_strip_all_tags(wp_unslash($_SERVER['HTTP_USER_AGENT'] ?? '')));
$agent = trim(@$ua['platform'] . ' ' . @$ua['browser']);
if (empty($agent)) {
$agent = 'unknown';
}
$last['timestamp'] = current_time('timestamp');
$last['url'] = wp_strip_all_tags(wp_unslash($_SERVER['REQUEST_URI'] ?? ''));
$last['user_agent'] = $agent;
array_unshift($log404, $last);
$max = abs(apply_filters('301_redirects_max_404_logs', 50));
$log404 = array_slice($log404, 0, $max);
update_option('301_redirects_404_log', $log404);
} // check_404
static function redirects_301_do_redirect()
{
$siteurl = get_bloginfo('url');
$actual_link = self::getUrl();
$all_redirects = $GLOBALS['redirectsplugins']->getAll();
if ($all_redirects) {
foreach ($all_redirects as $redirect_id) {
$la_redirect = $GLOBALS['redirectsplugins']->getFields($redirect_id);
$la_old_link = str_replace($siteurl, "", $la_redirect['old_link']);
if ($actual_link == $siteurl . $la_old_link) {
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ' . $la_redirect['new_link'], true, 301);
die();
}
} // foreach
}
} // redirects_301_do_redirect
static function ajax_delete_rule()
{
$redirects = new Redirects;
check_ajax_referer('redirect_delete_rule');
if (isset($_POST['custom_id'])) {
if ($_POST['custom_id'] == 'all') {
$redirects->delete();
die('1');
} else {
$custom_id = (int) sanitize_text_field(wp_unslash($_POST['custom_id']));
$redirects->remove($custom_id);
die('1');
}
} else {
die();
}
} // ajax_delete_rule
static function getUrl()
{
$https = sanitize_text_field(wp_unslash($_SERVER["HTTPS"] ?? ''));
$host = sanitize_text_field(wp_unslash($_SERVER["HTTP_HOST"] ?? ''));
$request_url = sanitize_text_field(wp_unslash($_SERVER["REQUEST_URI"] ?? ''));
$url = ($https != 'on') ? 'http://' . $host . $request_url : 'https://' . $host . $request_url;
return $url;
} // getUrl
static function redirects_301_options()
{
$redirects = new Redirects;
$savedsuccesfully = false;
if (isset($_POST['links_audit_submit']) && check_admin_referer('ts_save_rules')) {
$redirects->delete();
if (!empty($_POST['title'])) {
//phpcs:ignore $_POST['title'] is an array and each value is sanitized individually below
$redirect_arr = $_POST['title']; //phpcs:ignore
foreach ($redirect_arr as $key => $redirect_title) {
$title = sanitize_text_field($redirect_title);
$section = array_key_exists($key, $_POST['section']) ? sanitize_text_field(wp_unslash($_POST['section'][$key] ?? '')) : '';
$new_link = sanitize_url(wp_unslash($_POST['new_link'][$key] ?? ''));
$old_link = sanitize_url(wp_unslash($_POST['old_link'][$key] ?? ''));
$redirects->edit($title, $section, $new_link, $old_link);
}
}
$savedsuccesfully = true;
}
?>
301 Redirects
All redirect rules have been saved.×
Add your old path /old-path-from-site/ (don't forget to start with a forward slash) in the old link field, and the new path /new-path-somewhere/ in the new link field. If you're redirecting to an external URL add the https:// prefix. Name and Section serve only for your organization and convenience.
Please rate the plugin ★★★★★ to keep it free & maintained . It only takes a minute to rate. Thank you! 👋
You currently don\'t have any data in the 404 error log. That means that you either just installed the plugin, or that you never had a 404 error happen which is awesome 🚀 !';
} else {
echo 'Need a more detailed 404 error log? With more data, more insights, per-day stats & an easier way to create redirect rules from 404 errors? Want to have a centralized log for all your websites in one place?
Upgrade to WP 301 Redirects PRO. ';
echo '';
echo '';
echo 'Date & Time ';
echo 'Target URL ';
echo 'User Device ';
echo 'User Location ';
echo 'Referal URL ';
echo ' ';
foreach ($log as $l) {
echo '';
echo '' . esc_html(human_time_diff(current_time('timestamp'), $l['timestamp'])) . ' ago ';
echo '' . esc_html($l['url']) . ' ';
echo '' . esc_html($l['user_agent']) . ' ';
echo 'Available in PRO ';
echo 'Available in PRO ';
echo ' ';
} // foreach
echo '
';
echo 'By default, the log is limited to the last fifty (chronologically) 404 errors. This is a safe number that ensures the log works on all sites and doesn\'t slow anything down. ';
echo 'The code imposes no limits on the log size and you can easily overwrite the default limit by using the 301_redirects_max_404_logs filter. Details are available in the FAQ .
';
echo 'If your site gets hundreds and thousands of 404 errors a day we suggesting upgrading to WP 301 Redirects PRO as it automatically fixes 404 errors caused by URL typos, provides a more robust log that can handle tens of thousands of entries, and offers more tools to manage 404 errors.
';
} // if 404
} // tab_404
// add widget to dashboard
static function add_widget()
{
if (current_user_can('manage_options')) {
add_meta_box('wp301_redirects_404_errors', '404 Errors Log', array(__CLASS__, 'widget_content'), 'dashboard', 'side', 'high');
}
} // add_widget
// render widget
static function widget_content()
{
$log = get_option('301_redirects_404_log', array());
if (!self::check_permalinks()) {
echo 'WARNING: 301 Redirects plugin requires that a permalink structure is set. The default (plain) WordPress permalink structure is not compatible with 301 Redirects. Please update the Permalink Structure .
';
return;
}
echo '';
if (!sizeof($log)) {
echo 'You currently don\'t have any data in the 404 error log. That means that you either just installed the plugin, or that you never had a 404 error happen which is awesome 🚀 !
';
echo 'Don\'t like seeing an empty error log? Or just want to see see if the log works? Open any nonexistent URL and then reload this page.
';
} else {
echo '';
echo '';
echo 'Date & Time ';
echo 'Target URL ';
echo 'User Device ';
echo ' ';
$i = 1;
foreach ($log as $l) {
echo '';
echo '' . esc_html(human_time_diff(current_time('timestamp'), $l['timestamp'])) . ' ago ';
echo '' . esc_html($l['url']) . ' ';
echo '' . esc_html($l['user_agent']) . ' ';
echo ' ';
$i++;
if ($i >= 6) {
break;
}
} // foreach
echo '
';
echo 'View the entire 404 error log in the 301 Redirects plugin or create new redirect rules to fix 404 errors.
';
}
} // widget_content
static function pro_dialog()
{
if (!self::is_plugin_page()) {
return;
}
$out = '';
$out .= '';
$out .= '
';
$out .= '
Limited PRO Launch Discount - all prices are LIFETIME ! Pay once & use forever! ';
$out .= '
';
$out .= '
';
$out .= '';
$out .= 'Lifetime Personal License ';
$out .= 'Lifetime Team License ';
$out .= 'Lifetime Agency License ';
$out .= ' ';
$out .= '';
$out .= '$79 /year$49 /lifetime ';
$out .= '$159 /year$59 /lifetime ';
$out .= '$299 /year$99 /lifetime ';
$out .= ' ';
$out .= '';
$out .= '1 Site License ($49 per site) ';
$out .= '5 Sites License ($12 per site) ';
$out .= '100 Sites License ($1 per site) ';
$out .= ' ';
$out .= '';
$out .= ' Advanced Redirects Management ';
$out .= ' Advanced Redirects Management ';
$out .= ' Advanced Redirects Management ';
$out .= ' ';
$out .= '';
$out .= ' Advanced URL Matching Rules ';
$out .= ' Advanced URL Matching Rules ';
$out .= ' Advanced URL Matching Rules ';
$out .= ' ';
$out .= '';
$out .= ' Auto-fix URL Typos ';
$out .= ' Auto-fix URL Typos ';
$out .= ' Auto-fix URL Typos ';
$out .= ' ';
$out .= '';
$out .= ' Detailed 404 & Redirect Stats ';
$out .= ' Detailed 404 & Redirect Stats ';
$out .= ' Detailed 404 & Redirect Stats ';
$out .= ' ';
$out .= '';
$out .= ' URL Cloaking ';
$out .= ' URL Cloaking ';
$out .= ' URL Cloaking ';
$out .= ' ';
$out .= '';
$out .= ' Licenses & Sites Manager (SaaS) ';
$out .= ' Licenses & Sites Manager (SaaS) ';
$out .= ' Licenses & Sites Manager (SaaS) ';
$out .= ' ';
$out .= '';
$out .= ' Remote Site Stats ';
$out .= ' Remote Site Stats ';
$out .= ' Remote Site Stats ';
$out .= ' ';
$out .= '';
$out .= ' White-label Mode ';
$out .= ' White-label Mode ';
$out .= ' White-label Mode ';
$out .= ' ';
$out .= '';
$out .= ' Full Plugin Rebranding ';
$out .= ' Full Plugin Rebranding ';
$out .= ' Full Plugin Rebranding ';
$out .= ' ';
$out .= '';
$out .= ' Branded PDF Reports ';
$out .= ' Branded PDF Reports ';
$out .= ' Branded PDF Reports ';
$out .= ' ';
$out .= '';
$out .= ' Lifetime Updates & Support ';
$out .= ' Lifetime Updates & Support ';
$out .= ' Lifetime Updates & Support ';
$out .= ' ';
$out .= '';
$out .= 'one-time payment BUY NOW ';
$out .= 'one-time payment BUY NOW ';
$out .= 'one-time payment BUY NOW ';
$out .= ' ';
$out .= '
';
$out .= '
';
ts_redirects::wp_kses_wf($out);
} // pro_dialog
static function wp_kses_wf($html)
{
add_filter('safe_style_css', function ($styles) {
$styles_wf = array(
'text-align',
'margin',
'color',
'float',
'border',
'background',
'background-color',
'border-bottom',
'border-bottom-color',
'border-bottom-style',
'border-bottom-width',
'border-collapse',
'border-color',
'border-left',
'border-left-color',
'border-left-style',
'border-left-width',
'border-right',
'border-right-color',
'border-right-style',
'border-right-width',
'border-spacing',
'border-style',
'border-top',
'border-top-color',
'border-top-style',
'border-top-width',
'border-width',
'caption-side',
'clear',
'cursor',
'direction',
'font',
'font-family',
'font-size',
'font-style',
'font-variant',
'font-weight',
'height',
'letter-spacing',
'line-height',
'margin-bottom',
'margin-left',
'margin-right',
'margin-top',
'overflow',
'padding',
'padding-bottom',
'padding-left',
'padding-right',
'padding-top',
'text-decoration',
'text-indent',
'vertical-align',
'width',
'display',
);
foreach ($styles_wf as $style_wf) {
$styles[] = $style_wf;
}
return $styles;
});
$allowed_tags = wp_kses_allowed_html('post');
$allowed_tags['input'] = array(
'type' => true,
'style' => true,
'class' => true,
'id' => true,
'checked' => true,
'disabled' => true,
'name' => true,
'size' => true,
'placeholder' => true,
'value' => true,
'data-*' => true,
'size' => true,
'disabled' => true
);
$allowed_tags['textarea'] = array(
'type' => true,
'style' => true,
'class' => true,
'id' => true,
'checked' => true,
'disabled' => true,
'name' => true,
'size' => true,
'placeholder' => true,
'value' => true,
'data-*' => true,
'cols' => true,
'rows' => true,
'disabled' => true,
'autocomplete' => true
);
$allowed_tags['select'] = array(
'type' => true,
'style' => true,
'class' => true,
'id' => true,
'checked' => true,
'disabled' => true,
'name' => true,
'size' => true,
'placeholder' => true,
'value' => true,
'data-*' => true,
'multiple' => true,
'disabled' => true
);
$allowed_tags['option'] = array(
'type' => true,
'style' => true,
'class' => true,
'id' => true,
'checked' => true,
'disabled' => true,
'name' => true,
'size' => true,
'placeholder' => true,
'value' => true,
'selected' => true,
'data-*' => true
);
$allowed_tags['optgroup'] = array(
'type' => true,
'style' => true,
'class' => true,
'id' => true,
'checked' => true,
'disabled' => true,
'name' => true,
'size' => true,
'placeholder' => true,
'value' => true,
'selected' => true,
'data-*' => true,
'label' => true
);
$allowed_tags['a'] = array(
'href' => true,
'data-*' => true,
'class' => true,
'style' => true,
'id' => true,
'target' => true,
'data-*' => true,
'role' => true,
'aria-controls' => true,
'aria-selected' => true,
'disabled' => true
);
$allowed_tags['div'] = array(
'style' => true,
'class' => true,
'id' => true,
'data-*' => true,
'role' => true,
'aria-labelledby' => true,
'value' => true,
'aria-modal' => true,
'tabindex' => true
);
$allowed_tags['li'] = array(
'style' => true,
'class' => true,
'id' => true,
'data-*' => true,
'role' => true,
'aria-labelledby' => true,
'value' => true,
'aria-modal' => true,
'tabindex' => true
);
$allowed_tags['span'] = array(
'style' => true,
'class' => true,
'id' => true,
'data-*' => true,
'aria-hidden' => true
);
$allowed_tags['style'] = array(
'class' => true,
'id' => true,
'type' => true
);
$allowed_tags['fieldset'] = array(
'class' => true,
'id' => true,
'type' => true
);
$allowed_tags['link'] = array(
'class' => true,
'id' => true,
'type' => true,
'rel' => true,
'href' => true,
'media' => true
);
$allowed_tags['form'] = array(
'style' => true,
'class' => true,
'id' => true,
'method' => true,
'action' => true,
'data-*' => true
);
$allowed_tags['script'] = array(
'class' => true,
'id' => true,
'type' => true,
'src' => true
);
echo wp_kses($html, $allowed_tags);
add_filter('safe_style_css', function ($styles) {
$styles_wf = array(
'text-align',
'margin',
'color',
'float',
'border',
'background',
'background-color',
'border-bottom',
'border-bottom-color',
'border-bottom-style',
'border-bottom-width',
'border-collapse',
'border-color',
'border-left',
'border-left-color',
'border-left-style',
'border-left-width',
'border-right',
'border-right-color',
'border-right-style',
'border-right-width',
'border-spacing',
'border-style',
'border-top',
'border-top-color',
'border-top-style',
'border-top-width',
'border-width',
'caption-side',
'clear',
'cursor',
'direction',
'font',
'font-family',
'font-size',
'font-style',
'font-variant',
'font-weight',
'height',
'letter-spacing',
'line-height',
'margin-bottom',
'margin-left',
'margin-right',
'margin-top',
'overflow',
'padding',
'padding-bottom',
'padding-left',
'padding-right',
'padding-top',
'text-decoration',
'text-indent',
'vertical-align',
'width'
);
foreach ($styles_wf as $style_wf) {
if (($key = array_search($style_wf, $styles)) !== false) {
unset($styles[$key]);
}
}
return $styles;
});
}
static function add_options_page()
{
add_options_page('301 Redirects', '301 Redirects', 'manage_options', '301-redirects', array(__CLASS__, 'redirects_301_options'));
} //redirects_301
static function admin_notices()
{
if (!self::check_permalinks()) {
echo '';
echo '
WARNING: 301 Redirects plugin requires that a permalink structure is set. The default (plain) WordPress permalink structure is not compatible with 301 Redirects. Please update the Permalink Structure .
';
echo '
';
}
} // admin_notices
static function check_permalinks()
{
global $wp_rewrite;
if (!isset($wp_rewrite->permalink_structure) || empty($wp_rewrite->permalink_structure)) {
return false;
} else {
return true;
}
} // check_permalinks
static function _deactivation()
{
delete_option('ts_301_redirection');
} // _deactivation
} // class ts_redirects
ts_redirects::init();
register_deactivation_hook(__FILE__, array('ts_redirects', '_deactivation'));