' . __( 'Settings' ) . ''; array_unshift($links, $settings_link); return $links; } /** * @global type $abj404spellChecker */ function suggestions() { global $abj404logic; global $abj404spellChecker; if (is_404()) { $options = $abj404logic->getOptions(); if (@$options['display_suggest'] == '1') { echo "
"; $requestedURL = esc_url($_SERVER['REQUEST_URI']); $urlParts = parse_url($requestedURL); $permalinks = $abj404spellChecker->findMatchingPosts($urlParts['path'], $options['suggest_cats'], $options['suggest_tags']); // Allowing some HTML. echo wp_kses($options['suggest_title'], array( 'h1' => array(), 'h2' => array(), 'h3' => array(), 'h4' => array(), 'h5' => array(), 'h6' => array(), 'i' => array(), 'em' => array(), 'strong' => array(), ) ); $displayed = 0; foreach ($permalinks as $k => $v) { $permalink = ABJ_404_Solution_Functions::permalinkInfoToArray($k, $v); if ($permalink['score'] >= $options['suggest_minscore']) { if ($displayed == 0) { // No need to escape since we're expecting HTML echo wp_kses($options['suggest_before'], array( 'ul' => array(), 'ol' => array(), 'li' => array(), ) ); } echo wp_kses($options['suggest_entrybefore'], array( 'ul' => array(), 'ol' => array(), 'li' => array(), ) ); echo "" . esc_attr($permalink['title']) . ""; if (is_user_logged_in() && current_user_can('manage_options')) { echo " (" . esc_html($permalink['score']) . ")"; } echo wp_kses($options['suggest_entryafter'], array( 'ul' => array(), 'ol' => array(), 'li' => array(), ) ); $displayed++; if ($displayed >= $options['suggest_max']) { break; } } else { break; } } if ($displayed >= 1) { echo wp_kses($options['suggest_after'], array( 'ul' => array(), 'ol' => array(), 'li' => array(), ) ); } else { echo wp_kses($options['suggest_noresults'], $allowedtags); } echo "
"; } } } /** * Process the 404s */ static function process404() { // Bail out if // not on 404 error page - because we're not supposed to, or // if we're currently on an admin screen - because we want admins to see 404s?, or // if we're receiving a "close connection" signal - because the user is no longer there. // Note: is_admin() does not mean the user is an admin - it returns true when the user is on an admin screen. if ((!is_404()) || (is_admin())) { return; } global $abj404dao; global $abj404logic; global $abj404connector; global $abj404spellChecker; $urlRequest = esc_url(preg_replace('/\?.*/', '', esc_url($_SERVER['REQUEST_URI']))); $adminURL = parse_url(admin_url(), PHP_URL_PATH); if (substr($urlRequest, 0, strlen($adminURL)) == $adminURL) { ABJ_404_Solution_Functions::debugMessage("Ignoring request for admin URL: " . $urlRequest); return; } // remove the home directory from the URL parts because it should not be considered for spell checking. $urlHomeDirectory = parse_url(get_home_url(), PHP_URL_PATH); if (substr($urlRequest, 0, strlen($urlHomeDirectory)) == $urlHomeDirectory) { $urlRequest = substr($urlRequest, strlen($urlHomeDirectory)); } $urlParts = parse_url($urlRequest); $requestedURL = $urlParts['path']; $requestedURL .= $abj404connector->sortQueryParts($urlParts); // Get URL data if it's already in our database $redirect = $abj404dao->getRedirectForURL($requestedURL); $options = $abj404logic->getOptions(); if (ABJ_404_Solution_Functions::isDebug()) { ABJ_404_Solution_Functions::debugMessage("Processing 404 for URL: " . $requestedURL . " | Redirect: " . wp_kses(json_encode($redirect), array()) . " | is_single(): " . is_single() . " | " . "is_page(): " . is_page() . " | is_feed(): " . is_feed() . " | is_trackback(): " . is_trackback() . " | is_preview(): " . is_preview() . " | options: " . wp_kses(json_encode($options), array())); } if ($requestedURL != "") { // if we already know where to go then go there. if ($redirect['id'] != '0') { // A redirect record exists. $abj404connector->processRedirect($redirect); // we will never reach this line unless an error happens. return; } // -------------------------------------------------------------- // try a permalink change. $slugPermalink = $abj404spellChecker->getPermalinkUsingSlug($requestedURL); if (!empty($slugPermalink)) { $redirectType = $abj404logic->permalinkTypeToRedirectType($slugPermalink['type']); $redirect_id = $abj404dao->setupRedirect($requestedURL, ABJ404_AUTO, $redirectType, $slugPermalink['id'], $options['default_redirect'], 0); $abj404dao->logRedirectHit($redirect_id, $slugPermalink['link']); wp_redirect(esc_url($slugPermalink['link']), esc_html($options['default_redirect'])); exit; } // -------------------------------------------------------------- // try spell checking. $permalink = $abj404spellChecker->getPermalinkUsingSpelling($requestedURL); if (!empty($permalink)) { $redirectType = $abj404logic->permalinkTypeToRedirectType($permalink['type']); $redirect_id = $abj404dao->setupRedirect($requestedURL, ABJ404_AUTO, $redirectType, $permalink['id'], $options['default_redirect'], 0); $abj404dao->logRedirectHit($redirect_id, $permalink['link']); wp_redirect(esc_url($permalink['link']), esc_html($options['default_redirect'])); exit; } } else { if (is_single() || is_page()) { if (!is_feed() && !is_trackback() && !is_preview()) { $theID = get_the_ID(); $permalink = ABJ_404_Solution_Functions::permalinkInfoToArray($theID . "|POST", 0); $urlParts = parse_url($permalink['link']); $perma_link = $urlParts['path']; $paged = get_query_var('page') ? esc_html(get_query_var('page')) : FALSE; if (!$paged === FALSE) { if ($urlParts[query] == "") { if (substr($perma_link, -1) == "/") { $perma_link .= $paged . "/"; } else { $perma_link .= "/" . $paged; } } else { $urlParts['query'] .= "&page=" . $paged; } } $perma_link .= $abj404connector->sortQueryParts($urlParts); // Check for forced permalinks. if (@$options['force_permalinks'] == '1' && @$options['auto_redirects'] == '1') { if ($requestedURL != $perma_link) { if ($redirect['id'] != '0') { $abj404connector->processRedirect($redirect); } else { $redirect_id = $abj404dao->setupRedirect(esc_url($requestedURL), ABJ404_AUTO, ABJ404_POST, $permalink['id'], $options['default_redirect'], 0); $abj404dao->logRedirectHit($redirect_id, $permalink['link']); wp_redirect(esc_url($permalink['link']), esc_html($options['default_redirect'])); exit; } } } if ($requestedURL == $perma_link) { // Not a 404 Link. Check for matches. if ($options['remove_matches'] == '1') { if ($redirect['id'] != '0') { $abj404dao->deleteRedirect($redirect['id']); } } } } } } // --------------------------------------- // if there's a default 404 page specified then use that. $dest404page = (isset($options['dest404page']) ? $options['dest404page'] : 0); if ($dest404page > 0) { $permalink = ABJ_404_Solution_Functions::permalinkInfoToArray($dest404page . "|POST", 0); $redirect_id = $abj404dao->setupRedirect($requestedURL, ABJ404_AUTO, ABJ404_POST, $permalink['id'], $options['default_redirect'], 0); $abj404dao->logRedirectHit($redirect_id, $permalink['link']); wp_redirect(esc_url($permalink['link']), esc_html($options['default_redirect'])); exit; } // --------------------------------------- // give up. log the 404. if (@$options['capture_404'] == '1') { $redirect_id = $abj404dao->setupRedirect($requestedURL, ABJ404_CAPTURED, 0, 0, $options['default_redirect'], 0); $abj404dao->logRedirectHit($redirect_id, '404'); } else { if (ABJ_404_Solution_Functions::isDebug()) { ABJ_404_Solution_Functions::debugMessage("No permalink found to redirect to. capture_404 is off. Requested URL: " . $requestedURL . " | Redirect: " . wp_kses(json_encode($redirect), array()) . " | is_single(): " . is_single() . " | " . "is_page(): " . is_page() . " | is_feed(): " . is_feed() . " | is_trackback(): " . is_trackback() . " | is_preview(): " . is_preview() . " | options: " . wp_kses(json_encode($options), array())); } } } /** Sort the QUERY parts of the requested URL. * This is in place because these are stored as part of the URL in the database and used for forwarding to another page. * This is done because sometimes different query parts result in a completely different page. Therefore we have to * take into account the query part of the URL (?query=part) when looking for a page to redirect to. * * Here we sort the query parts so that the same request will always look the same. * @param type $urlParts * @return string */ function sortQueryParts($urlParts) { if (@$urlParts['query'] == "") { return ""; } $url = ""; $queryString = array(); $urlQuery = $urlParts['query']; $queryParts = preg_split("/[;&]/", $urlQuery); foreach ($queryParts as $query) { if (strpos($query, "=") === false) { $queryString[$query] = ''; } else { $stringParts = preg_split("/=/", $query); $queryString[$stringParts[0]] = $stringParts[1]; } } ksort($queryString); $x = 0; $newQS = ""; foreach ($queryString as $key => $value) { if ($x != 0) { $newQS .= "&"; } $newQS .= $key; if ($value != "") { $newQS .= "=" . $value; } $x++; } if ($newQS != "") { $url .= "?" . $newQS; } return esc_url($url); } /** * Redirect canonicals */ static function redirectCanonical($redirect, $request) { global $abj404dao; global $abj404connector; global $abj404logic; if (is_single() || is_page()) { if (!is_feed() && !is_trackback() && !is_preview()) { $options = $abj404logic->getOptions(); // Sanitizing options. foreach ($options as $key => $value) { $key = wp_kses_post($key); $options[$key] = wp_kses_post($value); } $urlRequest = esc_url($_SERVER['REQUEST_URI']); $urlParts = parse_url($urlRequest); $requestedURL = $urlParts['path']; $requestedURL .= $abj404connector->sortQueryParts($urlParts); // Get URL data if it's already in our database. $data = $abj404dao->getRedirectForURL($requestedURL); if ($data['id'] != '0') { $abj404connector->processRedirect($data); } else { if ($options['auto_redirects'] == '1' && $options['force_permalinks'] == '1') { $theID = get_the_ID(); $permalink = ABJ_404_Solution_Functions::permalinkInfoToArray($theID . "|POST", 0); $urlParts = parse_url($permalink['link']); $perma_link = $urlParts['path']; $paged = get_query_var('page') ? esc_html(get_query_var('page')) : FALSE; if (!$paged === FALSE) { if ($urlParts[query] == "") { if (substr($perma_link, -1) == "/") { $perma_link .= $paged . "/"; } else { $perma_link .= "/" . $paged; } } else { $urlParts['query'] .= "&page=" . $paged; } } $perma_link .= $abj404connector->sortQueryParts($urlParts); if ($requestedURL != $perma_link) { $redirect_id = $abj404dao->setupRedirect($requestedURL, ABJ404_AUTO, ABJ404_POST, $theID, $options['default_redirect'], 0); $abj404dao->logRedirectHit($redirect_id, $perma_link); wp_redirect(esc_url($perma_link), esc_html($options['default_redirect'])); exit; } } } } } if (is_404()) { return false; } return $redirect; } /** Redirect to the page specified. * @global type $abj404dao * @param type $redirect */ function processRedirect($redirect) { global $abj404dao; if (( $redirect['status'] != ABJ404_MANUAL && $redirect['status'] != ABJ404_AUTO ) || $redirect['disabled'] != 0) { // It's a redirect that has been deleted, ignored, or captured. ABJ_404_Solution_Functions::errorMessage("processRedirect() was called with bad redirect data. Data: " . wp_kses(json_encode($redirect), array())); return; } if ($redirect['type'] == ABJ404_EXTERNAL) { //It's a external url setup by the user $abj404dao->logRedirectHit($redirect['id'], $redirect['final_dest']); wp_redirect(esc_url($redirect['final_dest']), esc_html($redirect['code'])); exit; } $key = ""; if ($redirect['type'] == ABJ404_POST) { $key = $redirect['final_dest'] . "|POST"; } else if ($redirect['type'] == ABJ404_CAT) { $key = $redirect['final_dest'] . "|CAT"; } else if ($redirect['type'] == ABJ404_TAG) { $key = $redirect['final_dest'] . "|TAG"; } else { ABJ_404_Solution_Functions::errorMessage("Unrecognized redirect type in Connector: " . wp_kses(json_encode($redirect), array())); } if ($key != "") { $permalink = ABJ_404_Solution_Functions::permalinkInfoToArray($key, 0); $abj404dao->logRedirectHit($redirect['id'], $permalink['link']); wp_redirect(esc_url($permalink['link']), esc_html($redirect['code'])); exit; } } /** Display an admin dashboard notification. * e.g. There are 29 captured 404 URLs that need to be processed. * @global type $pagenow * @global type $abj404dao * @global type $abj404logic * @global type $abj404view */ static function echoDashboardNotification() { if (!is_admin() || !current_user_can('administrator')) { return; } global $pagenow; global $abj404dao; global $abj404logic; global $abj404view; if (current_user_can('manage_options')) { if (( @$_GET['page'] == "abj404_solution" ) || ( $pagenow == 'index.php' && (!isset($_GET['page']) ) )) { $options = $abj404logic->getOptions(); if (isset($options['admin_notification']) && $options['admin_notification'] != '0') { $captured = $abj404dao->getCapturedCountForNotification(); if ($captured >= $options['admin_notification']) { echo $abj404view->getDashboardNotification($captured); } } } } } static function addMainSettingsPageLink() { if (!is_admin() || !current_user_can('administrator')) { return; } global $menu; global $abj404dao; global $abj404logic; $options = $abj404logic->getOptions(); $pageName = "404 Solution"; // Admin notice if (isset($options['admin_notification']) && $options['admin_notification'] != '0') { $captured = $abj404dao->getCapturedCountForNotification(); if (isset($options['admin_notification']) && $captured >= $options['admin_notification']) { $pageName .= " " . esc_html($captured) . ""; $pos = strpos($menu[80][0], 'update-plugins'); if ($pos === false) { $menu[80][0] = $menu[80][0] . " 1"; } } } // this adds the settings link at Settings->404 Solution. add_options_page('404 Solution', $pageName, 'manage_options', 'abj404_solution', 'ABJ_404_Solution_View::handleMainAdminPageActionAndDisplay'); } } ABJ_404_Solution_WordPress_Connector::init();