Archived
1025 lines
32 KiB
PHP
1025 lines
32 KiB
PHP
<?php
|
|
/**
|
|
* @package Internals
|
|
*/
|
|
|
|
if ( ! defined( 'WPSEO_VERSION' ) ) {
|
|
header( 'Status: 403 Forbidden' );
|
|
header( 'HTTP/1.1 403 Forbidden' );
|
|
exit();
|
|
}
|
|
|
|
|
|
/**
|
|
* Run the upgrade procedures.
|
|
*
|
|
* @todo - [JRF => Yoast] check: if upgrade is run on multi-site installation, upgrade for all sites ?
|
|
* Maybe not necessary as it is now run on plugins_loaded, so upgrade will run as soon as any page
|
|
* on a site is requested.
|
|
*/
|
|
function wpseo_do_upgrade() {
|
|
/* Make sure title_test and description_test functions are available */
|
|
require_once( WPSEO_PATH . 'inc/wpseo-non-ajax-functions.php' );
|
|
|
|
$option_wpseo = get_option( 'wpseo' );
|
|
|
|
WPSEO_Options::maybe_set_multisite_defaults( false );
|
|
|
|
if ( $option_wpseo['version'] === '' || version_compare( $option_wpseo['version'], '1.2', '<' ) ) {
|
|
add_action( 'init', 'wpseo_title_test' );
|
|
}
|
|
|
|
if ( $option_wpseo['version'] === '' || version_compare( $option_wpseo['version'], '1.4.13', '<' ) ) {
|
|
// Run description test once theme has loaded
|
|
add_action( 'init', 'wpseo_description_test' );
|
|
}
|
|
|
|
if ( $option_wpseo['version'] === '' || version_compare( $option_wpseo['version'], '1.4.15', '<' ) ) {
|
|
add_action( 'shutdown', 'flush_rewrite_rules' );
|
|
}
|
|
|
|
if ( version_compare( $option_wpseo['version'], '1.5.0', '<' ) ) {
|
|
|
|
// Clean up options and meta
|
|
WPSEO_Options::clean_up( null, $option_wpseo['version'] );
|
|
WPSEO_Meta::clean_up();
|
|
|
|
// Add new capabilities on upgrade
|
|
wpseo_add_capabilities();
|
|
}
|
|
|
|
/* Only correct the breadcrumb defaults for upgrades from v1.5+ to v1.5.2.3, upgrades from earlier version
|
|
will already get this functionality in the clean_up routine. */
|
|
if ( version_compare( $option_wpseo['version'], '1.4.25', '>' ) && version_compare( $option_wpseo['version'], '1.5.2.3', '<' ) ) {
|
|
add_action( 'init', array( 'WPSEO_Options', 'bring_back_breadcrumb_defaults' ), 3 );
|
|
}
|
|
|
|
if ( version_compare( $option_wpseo['version'], '1.4.25', '>' ) && version_compare( $option_wpseo['version'], '1.5.2.4', '<' ) ) {
|
|
/* Make sure empty maintax/mainpt strings will convert to 0 */
|
|
WPSEO_Options::clean_up( 'wpseo_internallinks', $option_wpseo['version'] );
|
|
|
|
/* Remove slashes from taxonomy meta texts */
|
|
WPSEO_Options::clean_up( 'wpseo_taxonomy_meta', $option_wpseo['version'] );
|
|
}
|
|
|
|
/* Clean up stray wpseo_ms options from the options table, option should only exist in the sitemeta table */
|
|
delete_option( 'wpseo_ms' );
|
|
|
|
|
|
// Make sure version nr gets updated for any version without specific upgrades
|
|
$option_wpseo = get_option( 'wpseo' ); // re-get to make sure we have the latest version
|
|
if ( version_compare( $option_wpseo['version'], WPSEO_VERSION, '<' ) ) {
|
|
update_option( 'wpseo', $option_wpseo );
|
|
}
|
|
|
|
// Make sure all our options always exist - issue #1245
|
|
WPSEO_Options::ensure_options_exist();
|
|
}
|
|
|
|
|
|
if ( ! function_exists( 'initialize_wpseo_front' ) ) {
|
|
function initialize_wpseo_front() {
|
|
$GLOBALS['wpseo_front'] = new WPSEO_Frontend;
|
|
}
|
|
}
|
|
|
|
|
|
if ( ! function_exists( 'yoast_breadcrumb' ) ) {
|
|
/**
|
|
* Template tag for breadcrumbs.
|
|
*
|
|
* @todo [JRF => Yoast/whomever] We could probably get rid of the 'breadcrumbs-enable' option key
|
|
* as the file is now only loaded when the template tag is encountered anyway.
|
|
* Only issue with that would be the removal of the bbPress crumb from within wpseo_frontend_init()
|
|
* in wpseo.php which is also based on this setting.
|
|
* Whether or not to show the bctitle field within meta boxes is also based on this setting, but
|
|
* showing these when someone hasn't implemented the template tag shouldn't really give cause for concern.
|
|
* Other than that, leaving the setting is an easy way to enable/disable the bc without having to
|
|
* edit the template files again, but having to manually enable when you've added the template tag
|
|
* in your theme is kind of double, so I'm undecided about what to do.
|
|
* I guess I'm leaning towards removing the option key.
|
|
*
|
|
* @param string $before What to show before the breadcrumb.
|
|
* @param string $after What to show after the breadcrumb.
|
|
* @param bool $display Whether to display the breadcrumb (true) or return it (false).
|
|
*
|
|
* @return string
|
|
*/
|
|
function yoast_breadcrumb( $before = '', $after = '', $display = true ) {
|
|
$options = get_option( 'wpseo_internallinks' );
|
|
|
|
if ( $options['breadcrumbs-enable'] === true ) {
|
|
return WPSEO_Breadcrumbs::breadcrumb( $before, $after, $display );
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add the bulk edit capability to the proper default roles.
|
|
*/
|
|
function wpseo_add_capabilities() {
|
|
$roles = array(
|
|
'administrator',
|
|
'editor',
|
|
'author',
|
|
'contributor',
|
|
);
|
|
|
|
$roles = apply_filters( 'wpseo_bulk_edit_roles', $roles );
|
|
|
|
foreach ( $roles as $role ) {
|
|
$r = get_role( $role );
|
|
if ( $r ) {
|
|
$r->add_cap( 'wpseo_bulk_edit' );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Remove the bulk edit capability from the proper default roles.
|
|
*/
|
|
function wpseo_remove_capabilities() {
|
|
$roles = array(
|
|
'administrator',
|
|
'editor',
|
|
'author',
|
|
'contributor',
|
|
);
|
|
|
|
$roles = apply_filters( 'wpseo_bulk_edit_roles', $roles );
|
|
|
|
foreach ( $roles as $role ) {
|
|
$r = get_role( $role );
|
|
if ( $r ) {
|
|
$r->remove_cap( 'wpseo_bulk_edit' );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Replace `%%variable_placeholders%%` with their real value based on the current requested page/post/cpt
|
|
*
|
|
* @param string $string the string to replace the variables in.
|
|
* @param object $args the object some of the replacement values might come from, could be a post, taxonomy or term.
|
|
* @param array $omit variables that should not be replaced by this function.
|
|
* @return string
|
|
*/
|
|
function wpseo_replace_vars( $string, $args, $omit = array() ) {
|
|
$replacer = new WPSEO_Replace_Vars;
|
|
return $replacer->replace( $string, $args, $omit );
|
|
}
|
|
|
|
/**
|
|
* Register a new variable replacement
|
|
*
|
|
* This function is for use by other plugins/themes to easily add their own additional variables to replace.
|
|
* This function should be called from a function on the 'wpseo_register_extra_replacements' action hook.
|
|
* The use of this function is preferred over the older 'wpseo_replacements' filter as a way to add new replacements.
|
|
* The 'wpseo_replacements' filter should still be used to adjust standard WPSEO replacement values.
|
|
* The function can not be used to replace standard WPSEO replacement value functions and will thrown a warning
|
|
* if you accidently try.
|
|
* To avoid conflicts with variables registered by WPSEO and other themes/plugins, try and make the
|
|
* name of your variable unique. Variable names also can not start with "%%cf_" or "%%ct_" as these are reserved
|
|
* for the standard WPSEO variable variables 'cf_<custom-field-name>', 'ct_<custom-tax-name>' and
|
|
* 'ct_desc_<custom-tax-name>'.
|
|
* The replacement function will be passed the undelimited name (i.e. stripped of the %%) of the variable
|
|
* to replace in case you need it.
|
|
*
|
|
* Example code:
|
|
* <code>
|
|
* <?php
|
|
* function retrieve_var1_replacement( $var1 ) {
|
|
* return 'your replacement value';
|
|
* }
|
|
*
|
|
* function register_my_plugin_extra_replacements() {
|
|
* wpseo_register_var_replacement( '%%myvar1%%', 'retrieve_var1_replacement', 'advanced', 'this is a help text for myvar1' );
|
|
* wpseo_register_var_replacement( 'myvar2', array( 'class', 'method_name' ), 'basic', 'this is a help text for myvar2' );
|
|
* }
|
|
* add_action( 'wpseo_register_extra_replacements', 'register_my_plugin_extra_replacements' );
|
|
* ?>
|
|
* </code>
|
|
*
|
|
* @since 1.5.4
|
|
*
|
|
* @param string $var The name of the variable to replace, i.e. '%%var%%'
|
|
* - the surrounding %% are optional
|
|
* @param mixed $replace_function Function or method to call to retrieve the replacement value for the variable
|
|
* Uses the same format as add_filter/add_action function parameter and
|
|
* should *return* the replacement value. DON'T echo it!
|
|
* @param string $type Type of variable: 'basic' or 'advanced', defaults to 'advanced'
|
|
* @param string $help_text Help text to be added to the help tab for this variable
|
|
* @return bool Whether the replacement function was succesfully registered
|
|
*/
|
|
function wpseo_register_var_replacement( $var, $replace_function, $type = 'advanced', $help_text = '' ) {
|
|
return WPSEO_Replace_Vars::register_replacement( $var, $replace_function, $type, $help_text );
|
|
}
|
|
|
|
/**
|
|
* Strip out the shortcodes with a filthy regex, because people don't properly register their shortcodes.
|
|
*
|
|
* @param string $text input string that might contain shortcodes
|
|
* @return string $text string without shortcodes
|
|
*/
|
|
function wpseo_strip_shortcode( $text ) {
|
|
return preg_replace( '`\[[^\]]+\]`s', '', $text );
|
|
}
|
|
|
|
/**
|
|
* Redirect /sitemap.xml to /sitemap_index.xml
|
|
*/
|
|
function wpseo_xml_redirect_sitemap() {
|
|
global $wp_query;
|
|
|
|
$current_url = ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ) ? 'https://' : 'http://';
|
|
$current_url .= sanitize_text_field( $_SERVER['SERVER_NAME'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
|
|
|
|
// must be 'sitemap.xml' and must be 404
|
|
if ( home_url( '/sitemap.xml' ) == $current_url && $wp_query->is_404 ) {
|
|
wp_redirect( home_url( '/sitemap_index.xml' ) );
|
|
exit;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize sitemaps. Add sitemap & XSL rewrite rules and query vars
|
|
*/
|
|
function wpseo_xml_sitemaps_init() {
|
|
$options = get_option( 'wpseo_xml' );
|
|
if ( $options['enablexmlsitemap'] !== true ) {
|
|
return;
|
|
}
|
|
|
|
// redirects sitemap.xml to sitemap_index.xml
|
|
add_action( 'template_redirect', 'wpseo_xml_redirect_sitemap', 0 );
|
|
|
|
if ( ! is_object( $GLOBALS['wp'] ) ) {
|
|
return;
|
|
}
|
|
|
|
$GLOBALS['wp']->add_query_var( 'sitemap' );
|
|
$GLOBALS['wp']->add_query_var( 'sitemap_n' );
|
|
$GLOBALS['wp']->add_query_var( 'xsl' );
|
|
add_rewrite_rule( 'sitemap_index\.xml$', 'index.php?sitemap=1', 'top' );
|
|
add_rewrite_rule( '([^/]+?)-sitemap([0-9]+)?\.xml$', 'index.php?sitemap=$matches[1]&sitemap_n=$matches[2]', 'top' );
|
|
add_rewrite_rule( '([a-z]+)?-?sitemap\.xsl$', 'index.php?xsl=$matches[1]', 'top' );
|
|
}
|
|
|
|
add_action( 'init', 'wpseo_xml_sitemaps_init', 1 );
|
|
|
|
/**
|
|
* Notify search engines of the updated sitemap.
|
|
*/
|
|
function wpseo_ping_search_engines( $sitemapurl = null ) {
|
|
// Don't ping if blog is not public
|
|
if ( '0' == get_option( 'blog_public' ) ) {
|
|
return;
|
|
}
|
|
|
|
$options = get_option( 'wpseo_xml' );
|
|
$base = $GLOBALS['wp_rewrite']->using_index_permalinks() ? 'index.php/' : '';
|
|
if ( $sitemapurl == null ) {
|
|
$sitemapurl = urlencode( home_url( $base . 'sitemap_index.xml' ) );
|
|
}
|
|
|
|
// Always ping Google and Bing, optionally ping Ask and Yahoo!
|
|
wp_remote_get( 'http://www.google.com/webmasters/tools/ping?sitemap=' . $sitemapurl );
|
|
wp_remote_get( 'http://www.bing.com/ping?sitemap=' . $sitemapurl );
|
|
|
|
if ( $options['xml_ping_yahoo'] === true ) {
|
|
wp_remote_get( 'http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=3usdTDLV34HbjQpIBuzMM1UkECFl5KDN7fogidABihmHBfqaebDuZk1vpLDR64I-&url=' . $sitemapurl );
|
|
}
|
|
|
|
if ( $options['xml_ping_ask'] === true ) {
|
|
wp_remote_get( 'http://submissions.ask.com/ping?sitemap=' . $sitemapurl );
|
|
}
|
|
}
|
|
add_action( 'wpseo_ping_search_engines', 'wpseo_ping_search_engines' );
|
|
|
|
|
|
function wpseo_store_tracking_response() {
|
|
if ( ! wp_verify_nonce( $_POST['nonce'], 'wpseo_activate_tracking' ) ) {
|
|
die();
|
|
}
|
|
|
|
$options = get_option( 'wpseo' );
|
|
$options['tracking_popup_done'] = true;
|
|
|
|
if ( $_POST['allow_tracking'] == 'yes' ) {
|
|
$options['yoast_tracking'] = true;
|
|
}
|
|
else {
|
|
$options['yoast_tracking'] = false;
|
|
}
|
|
|
|
update_option( 'wpseo', $options );
|
|
}
|
|
add_action( 'wp_ajax_wpseo_allow_tracking', 'wpseo_store_tracking_response' );
|
|
|
|
/**
|
|
* WPML plugin support: Set titles for custom types / taxonomies as translatable.
|
|
* It adds new keys to a wpml-config.xml file for a custom post type title, metadesc, title-ptarchive and metadesc-ptarchive fields translation.
|
|
* Documentation: http://wpml.org/documentation/support/language-configuration-files/
|
|
*
|
|
* @global $sitepress
|
|
* @param array $config
|
|
* @return array
|
|
*/
|
|
function wpseo_wpml_config( $config ) {
|
|
global $sitepress;
|
|
|
|
if ( ( is_array( $config ) && isset( $config['wpml-config']['admin-texts']['key'] ) ) && ( is_array( $config['wpml-config']['admin-texts']['key'] ) && $config['wpml-config']['admin-texts']['key'] !== array() ) ) {
|
|
$admin_texts = $config['wpml-config']['admin-texts']['key'];
|
|
foreach ( $admin_texts as $k => $val ) {
|
|
if ( $val['attr']['name'] === 'wpseo_titles' ) {
|
|
$translate_cp = array_keys( $sitepress->get_translatable_documents() );
|
|
if ( is_array( $translate_cp ) && $translate_cp !== array() ) {
|
|
foreach ( $translate_cp as $post_type ) {
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'title-'. $post_type;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'metadesc-'. $post_type;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'metakey-'. $post_type;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'title-ptarchive-'. $post_type;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'metadesc-ptarchive-'. $post_type;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'metakey-ptarchive-'. $post_type;
|
|
|
|
$translate_tax = $sitepress->get_translatable_taxonomies( false, $post_type );
|
|
if ( is_array( $translate_tax ) && $translate_tax !== array() ) {
|
|
foreach ( $translate_tax as $taxonomy ) {
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'title-tax-'. $taxonomy;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'metadesc-tax-'. $taxonomy;
|
|
$admin_texts[ $k ]['key'][]['attr']['name'] = 'metakey-tax-'. $taxonomy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
$config['wpml-config']['admin-texts']['key'] = $admin_texts;
|
|
}
|
|
|
|
return $config;
|
|
}
|
|
add_filter( 'icl_wpml_config_array', 'wpseo_wpml_config' );
|
|
|
|
|
|
/**
|
|
* Generate an HTML sitemap
|
|
*
|
|
* @param array $atts The attributes passed to the shortcode.
|
|
*
|
|
* @return string
|
|
*/
|
|
function wpseo_sitemap_handler( $atts ) {
|
|
|
|
$atts = shortcode_atts(
|
|
array(
|
|
'authors' => true,
|
|
'pages' => true,
|
|
'posts' => true,
|
|
'archives' => true,
|
|
),
|
|
$atts
|
|
);
|
|
|
|
$display_authors = ( $atts['authors'] === 'no' ) ? false : true;
|
|
$display_pages = ( $atts['pages'] === 'no' ) ? false : true;
|
|
$display_posts = ( $atts['posts'] === 'no' ) ? false : true;
|
|
$display_archives = ( $atts['archives'] === 'no' ) ? false : true;
|
|
|
|
$options = WPSEO_Options::get_all();
|
|
|
|
/* Delete the transient if any of these are no
|
|
@todo [JRF => whomever] have a good look at this, as this would basically mean that if any of these
|
|
are no, we'd never use the transient and would always build again from scratch which is very inefficient
|
|
Suggestion: have several different transients based on the variables chosen
|
|
*/
|
|
if ( $display_authors === false || $display_pages === false || $display_posts === false ) {
|
|
delete_transient( 'html-sitemap' );
|
|
}
|
|
|
|
// Get any existing copy of our transient data
|
|
if ( false !== ( $output = get_transient( 'html-sitemap' ) ) ) {
|
|
// $output .= 'CACHE'; // debug
|
|
// return $output;
|
|
}
|
|
|
|
$output = '';
|
|
|
|
// create author list
|
|
if ( $display_authors ) {
|
|
// use echo => false b/c shortcode format screws up
|
|
$author_list = wp_list_authors(
|
|
array(
|
|
'exclude_admin' => false,
|
|
'echo' => false,
|
|
)
|
|
);
|
|
|
|
if ( $author_list !== '' ) {
|
|
$output .= '
|
|
<h2 id="authors">' . __( 'Authors', 'wordpress-seo' ) . '</h2>
|
|
<ul>
|
|
' . $author_list . '
|
|
</ul>';
|
|
}
|
|
}
|
|
|
|
// create page list
|
|
if ( $display_pages ) {
|
|
// Some query magic to retrieve all pages that should be excluded, while preventing noindex pages that are set to
|
|
// "always" include in HTML sitemap from being excluded.
|
|
// @todo [JRF => whomever] check query efficiency using EXPLAIN
|
|
|
|
$exclude_query = "SELECT DISTINCT( post_id ) FROM {$GLOBALS['wpdb']->postmeta}
|
|
WHERE ( ( meta_key = '" . WPSEO_Meta::$meta_prefix . "sitemap-html-include' AND meta_value = 'never' )
|
|
OR ( meta_key = '" . WPSEO_Meta::$meta_prefix . "meta-robots-noindex' AND meta_value = '1' ) )
|
|
AND post_id NOT IN
|
|
( SELECT pm2.post_id FROM {$GLOBALS['wpdb']->postmeta} pm2
|
|
WHERE pm2.meta_key = '" . WPSEO_Meta::$meta_prefix . "sitemap-html-include' AND pm2.meta_value = 'always')
|
|
ORDER BY post_id ASC";
|
|
$excluded_pages = $GLOBALS['wpdb']->get_results( $exclude_query );
|
|
|
|
$exclude = array();
|
|
if ( is_array( $excluded_pages ) && $excluded_pages !== array() ) {
|
|
foreach ( $excluded_pages as $page ) {
|
|
$exclude[] = $page->post_id;
|
|
}
|
|
}
|
|
unset( $excluded_pages, $page );
|
|
|
|
/**
|
|
* This filter allows excluding more pages should you wish to from the HTML sitemap.
|
|
*/
|
|
$exclude = implode( ',', apply_filters( 'wpseo_html_sitemap_page_exclude', $exclude ) );
|
|
|
|
$page_list = wp_list_pages(
|
|
array(
|
|
'exclude' => $exclude,
|
|
'title_li' => '',
|
|
'echo' => false,
|
|
)
|
|
);
|
|
|
|
if ( $page_list !== '' ) {
|
|
$output .= '
|
|
<h2 id="pages">' . __( 'Pages', 'wordpress-seo' ) . '</h2>
|
|
<ul>
|
|
' . $page_list . '
|
|
</ul>';
|
|
}
|
|
}
|
|
|
|
// create post list
|
|
if ( $display_posts ) {
|
|
// Add categories you'd like to exclude in the exclude here
|
|
// possibly have this controlled by shortcode params
|
|
$cats_map = '';
|
|
$cats = get_categories( 'exclude=' );
|
|
if ( is_array( $cats ) && $cats !== array() ) {
|
|
foreach ( $cats as $cat ) {
|
|
$args = array(
|
|
'post_type' => 'post',
|
|
'post_status' => 'publish',
|
|
'posts_per_page' => -1,
|
|
'cat' => $cat->cat_ID,
|
|
|
|
'meta_query' => array(
|
|
'relation' => 'OR',
|
|
// include if this key doesn't exists
|
|
array(
|
|
'key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex',
|
|
'value' => 'needs-a-value-anyway', // This is ignored, but is necessary...
|
|
'compare' => 'NOT EXISTS',
|
|
),
|
|
// OR if key does exists include if it is not 1
|
|
array(
|
|
'key' => WPSEO_Meta::$meta_prefix . 'meta-robots-noindex',
|
|
'value' => '1',
|
|
'compare' => '!=',
|
|
),
|
|
// OR this key overrides it
|
|
array(
|
|
'key' => WPSEO_Meta::$meta_prefix . 'sitemap-html-include',
|
|
'value' => 'always',
|
|
'compare' => '=',
|
|
),
|
|
),
|
|
);
|
|
|
|
$posts = get_posts( $args );
|
|
|
|
if ( is_array( $posts ) && $posts !== array() ) {
|
|
$posts_in_cat = '';
|
|
|
|
foreach ( $posts as $post ) {
|
|
$category = get_the_category( $post->ID );
|
|
|
|
// Only display a post link once, even if it's in multiple categories
|
|
if ( $category[0]->cat_ID == $cat->cat_ID ) {
|
|
$posts_in_cat .= '
|
|
<li><a href="' . esc_url( get_permalink( $post->ID ) ) . '">' . get_the_title( $post->ID ) . '</a></li>';
|
|
}
|
|
}
|
|
|
|
if ( $posts_in_cat !== '' ) {
|
|
$cats_map .= '
|
|
<li>
|
|
<h3>' . $cat->cat_name . '</h3>
|
|
<ul>
|
|
' . $posts_in_cat . '
|
|
</ul>
|
|
</li>';
|
|
}
|
|
}
|
|
unset( $posts, $post, $posts_in_cat, $category );
|
|
}
|
|
}
|
|
|
|
if ( $cats_map !== '' ) {
|
|
$output .= '
|
|
<h2 id="posts">' . __( 'Posts', 'wordpress-seo' ) . '</h2>
|
|
<ul>
|
|
' . $cats_map . '
|
|
</ul>';
|
|
}
|
|
unset( $cats_map, $cats, $cat, $args );
|
|
}
|
|
|
|
|
|
// get all public non-builtin post types
|
|
$args = array(
|
|
'public' => true,
|
|
'_builtin' => false,
|
|
);
|
|
$post_types = get_post_types( $args, 'object' );
|
|
|
|
if ( is_array( $post_types ) && $post_types !== array() ) {
|
|
|
|
// create an noindex array of post types and taxonomies
|
|
$noindex = array();
|
|
foreach ( $options as $key => $value ) {
|
|
if ( strpos( $key, 'noindex-' ) === 0 && $value === true ) {
|
|
$noindex[] = $key;
|
|
}
|
|
}
|
|
|
|
$archives = '';
|
|
|
|
// create custom post type list
|
|
foreach ( $post_types as $post_type ) {
|
|
if ( is_object( $post_type ) && ! in_array( 'noindex-' . $post_type->name, $noindex ) ) {
|
|
$output .= '
|
|
<h2 id="' . $post_type->name . '">' . esc_html( $post_type->label ) . '</h2>
|
|
<ul>
|
|
' . create_type_sitemap_template( $post_type ) . '
|
|
</ul>';
|
|
}
|
|
|
|
// create archives list
|
|
if ( $display_archives ) {
|
|
if ( is_object( $post_type ) && $post_type->has_archive && ! in_array( 'noindex-ptarchive-' . $post_type->name, $noindex ) ) {
|
|
$archives .= '<a href="' . esc_url( get_post_type_archive_link( $post_type->name ) ) . '">' . esc_html( $post_type->labels->name ) . '</a>';
|
|
|
|
$archives .= create_type_sitemap_template( $post_type );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( $archives !== '' ) {
|
|
$output .= '
|
|
<h2 id="archives">' . __( 'Archives', 'wordpress-seo' ) . '</h2>
|
|
<ul>
|
|
' . $archives .'
|
|
</ul>';
|
|
}
|
|
}
|
|
|
|
set_transient( 'html-sitemap', $output, 60 );
|
|
return $output;
|
|
}
|
|
|
|
add_shortcode( 'wpseo_sitemap', 'wpseo_sitemap_handler' );
|
|
|
|
|
|
/**
|
|
* @param $post_type
|
|
*
|
|
* @return string
|
|
*/
|
|
function create_type_sitemap_template( $post_type ) {
|
|
// $output = '<h2 id="' . $post_type->name . '">' . __( $post_type->label, 'wordpress-seo' ) . '</h2><ul>';
|
|
|
|
// Get all registered taxonomy of this post type
|
|
$taxs = get_object_taxonomies( $post_type->name, 'object' );
|
|
$output = '';
|
|
|
|
if ( is_array( $taxs ) && $taxs !== array() ) {
|
|
|
|
// Build the taxonomy tree
|
|
$walker = new Sitemap_Walker;
|
|
foreach ( $taxs as $key => $tax ) {
|
|
if ( $tax->public !== 1 ) {
|
|
continue;
|
|
}
|
|
|
|
$args = array(
|
|
'post_type' => $post_type->name,
|
|
'tax_query' => array(
|
|
array(
|
|
'taxonomy' => $key,
|
|
'field' => 'id',
|
|
'terms' => -1,
|
|
'operator' => 'NOT',
|
|
),
|
|
),
|
|
);
|
|
$query = new WP_Query( $args );
|
|
$title_li = $query->have_posts() ? $tax->labels->name : '';
|
|
|
|
$cats_list = wp_list_categories(
|
|
array(
|
|
'title_li' => $title_li,
|
|
'echo' => false,
|
|
'taxonomy' => $key,
|
|
'show_option_none' => '',
|
|
// 'hierarchical' => 0, // uncomment this for a flat list
|
|
|
|
'walker' => $walker,
|
|
'post_type' => $post_type->name, // arg used by the Walker class
|
|
)
|
|
);
|
|
|
|
if ( $cats_list !== '' ) {
|
|
$output .= $cats_list;
|
|
}
|
|
}
|
|
|
|
if ( $output !== '' ) {
|
|
$output .= '<br />';
|
|
}
|
|
}
|
|
return $output;
|
|
}
|
|
|
|
|
|
if ( ! function_exists( 'wpseo_calc' ) ) {
|
|
/**
|
|
* Do simple reliable math calculations without the risk of wrong results
|
|
* @see http://floating-point-gui.de/
|
|
* @see the big red warning on http://php.net/language.types.float.php
|
|
*
|
|
* In the rare case that the bcmath extension would not be loaded, it will return the normal calculation results
|
|
*
|
|
* @since 1.5.0
|
|
*
|
|
* @param mixed $number1 Scalar (string/int/float/bool)
|
|
* @param string $action Calculation action to execute. Valid input:
|
|
* '+' or 'add' or 'addition',
|
|
* '-' or 'sub' or 'subtract',
|
|
* '*' or 'mul' or 'multiply',
|
|
* '/' or 'div' or 'divide',
|
|
* '%' or 'mod' or 'modulus'
|
|
* '=' or 'comp' or 'compare'
|
|
* @param mixed $number2 Scalar (string/int/float/bool)
|
|
* @param bool $round Whether or not to round the result. Defaults to false.
|
|
* Will be disregarded for a compare operation
|
|
* @param int $decimals Decimals for rounding operation. Defaults to 0.
|
|
* @param int $precision Calculation precision. Defaults to 10.
|
|
* @return mixed Calculation Result or false if either or the numbers isn't scalar or
|
|
* an invalid operation was passed
|
|
* - for compare the result will always be an integer
|
|
* - for all other operations, the result will either be an integer (preferred)
|
|
* or a float
|
|
*/
|
|
function wpseo_calc( $number1, $action, $number2, $round = false, $decimals = 0, $precision = 10 ) {
|
|
static $bc;
|
|
|
|
if ( ! is_scalar( $number1 ) || ! is_scalar( $number2 ) ) {
|
|
return false;
|
|
}
|
|
|
|
if ( ! isset( $bc ) ) {
|
|
$bc = extension_loaded( 'bcmath' );
|
|
}
|
|
|
|
if ( $bc ) {
|
|
$number1 = strval( $number1 );
|
|
$number2 = strval( $number2 );
|
|
}
|
|
|
|
$result = null;
|
|
$compare = false;
|
|
|
|
switch ( $action ) {
|
|
case '+':
|
|
case 'add':
|
|
case 'addition':
|
|
$result = ( $bc ) ? bcadd( $number1, $number2, $precision ) /* string */ : ( $number1 + $number2 );
|
|
break;
|
|
|
|
case '-':
|
|
case 'sub':
|
|
case 'subtract':
|
|
$result = ( $bc ) ? bcsub( $number1, $number2, $precision ) /* string */ : ( $number1 - $number2 );
|
|
break;
|
|
|
|
case '*':
|
|
case 'mul':
|
|
case 'multiply':
|
|
$result = ( $bc ) ? bcmul( $number1, $number2, $precision ) /* string */ : ( $number1 * $number2 );
|
|
break;
|
|
|
|
case '/':
|
|
case 'div':
|
|
case 'divide':
|
|
if ( $bc ) {
|
|
$result = bcdiv( $number1, $number2, $precision ); // string, or NULL if right_operand is 0
|
|
}
|
|
elseif ( $number2 != 0 ) {
|
|
$result = $number1 / $number2;
|
|
}
|
|
|
|
if ( ! isset( $result ) ) {
|
|
$result = 0;
|
|
}
|
|
break;
|
|
|
|
case '%':
|
|
case 'mod':
|
|
case 'modulus':
|
|
if ( $bc ) {
|
|
$result = bcmod( $number1, $number2, $precision ); // string, or NULL if modulus is 0.
|
|
}
|
|
elseif ( $number2 != 0 ) {
|
|
$result = $number1 % $number2;
|
|
}
|
|
|
|
if ( ! isset( $result ) ) {
|
|
$result = 0;
|
|
}
|
|
break;
|
|
|
|
case '=':
|
|
case 'comp':
|
|
case 'compare':
|
|
$compare = true;
|
|
if ( $bc ) {
|
|
$result = bccomp( $number1, $number2, $precision ); // returns int 0, 1 or -1
|
|
}
|
|
else {
|
|
$result = ( $number1 == $number2 ) ? 0 : ( ( $number1 > $number2 ) ? 1 : -1 );
|
|
}
|
|
break;
|
|
}
|
|
|
|
if ( isset( $result ) ) {
|
|
if ( $compare === false ) {
|
|
if ( $round === true ) {
|
|
$result = round( floatval( $result ), $decimals );
|
|
if ( $decimals === 0 ) {
|
|
$result = (int) $result;
|
|
}
|
|
}
|
|
else {
|
|
$result = ( intval( $result ) == $result ) ? intval( $result ) : floatval( $result );
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if the web server is running on Apache
|
|
* @return bool
|
|
*/
|
|
function wpseo_is_apache() {
|
|
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stristr( $_SERVER['SERVER_SOFTWARE'], 'apache' ) !== false ) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if the web service is running on Nginx
|
|
*
|
|
* @return bool
|
|
*/
|
|
function wpseo_is_nginx() {
|
|
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && stristr( $_SERVER['SERVER_SOFTWARE'], 'nginx' ) !== false ) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* WordPress SEO breadcrumb shortcode
|
|
* [wpseo_breadcrumb]
|
|
*
|
|
* @return string
|
|
*/
|
|
function wpseo_shortcode_yoast_breadcrumb() {
|
|
return yoast_breadcrumb( '', '', false );
|
|
}
|
|
add_shortcode( 'wpseo_breadcrumb', 'wpseo_shortcode_yoast_breadcrumb' );
|
|
|
|
|
|
/**
|
|
* This invalidates our XML Sitemaps cache.
|
|
*
|
|
* @param $type
|
|
*/
|
|
function wpseo_invalidate_sitemap_cache( $type ) {
|
|
// Always delete the main index sitemaps cache, as that's always invalidated by any other change
|
|
delete_transient( 'wpseo_sitemap_cache_1' );
|
|
delete_transient( 'wpseo_sitemap_cache_' . $type );
|
|
}
|
|
|
|
add_action( 'deleted_term_relationships', 'wpseo_invalidate_sitemap_cache' );
|
|
|
|
/**
|
|
* Invalidate XML sitemap cache for taxonomy / term actions
|
|
*
|
|
* @param unsigned $unused
|
|
* @param string $type
|
|
*/
|
|
function wpseo_invalidate_sitemap_cache_terms( $unused, $type ) {
|
|
wpseo_invalidate_sitemap_cache( $type );
|
|
}
|
|
|
|
add_action( 'edited_terms', 'wpseo_invalidate_sitemap_cache_terms', 10, 2 );
|
|
add_action( 'clean_term_cache', 'wpseo_invalidate_sitemap_cache_terms', 10, 2 );
|
|
add_action( 'clean_object_term_cache', 'wpseo_invalidate_sitemap_cache_terms', 10, 2 );
|
|
|
|
/**
|
|
* Invalidate the XML sitemap cache for a post type when publishing or updating a post
|
|
*
|
|
* @param int $post_id
|
|
*/
|
|
function wpseo_invalidate_sitemap_cache_on_save_post( $post_id ) {
|
|
|
|
// If this is just a revision, don't invalidate the sitemap cache yet.
|
|
if ( wp_is_post_revision( $post_id ) ) {
|
|
return;
|
|
}
|
|
|
|
wpseo_invalidate_sitemap_cache( get_post_type( $post_id ) );
|
|
}
|
|
|
|
add_action( 'save_post', 'wpseo_invalidate_sitemap_cache_on_save_post' );
|
|
|
|
|
|
/**
|
|
* Emulate PHP native ctype_digit() function for when the ctype extension would be disabled *sigh*
|
|
* Only emulates the behaviour for when the input is a string, does not handle integer input as ascii value
|
|
*
|
|
* @param string $string
|
|
*
|
|
* @return bool
|
|
*/
|
|
if ( ! extension_loaded( 'ctype' ) || ! function_exists( 'ctype_digit' ) ) {
|
|
function ctype_digit( $string ) {
|
|
$return = false;
|
|
if ( ( is_string( $string ) && $string !== '' ) && preg_match( '`^\d+$`', $string ) === 1 ){
|
|
$return = true;
|
|
}
|
|
return $return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/********************** DEPRECATED FUNCTIONS **********************/
|
|
|
|
|
|
/**
|
|
* Get the value from the post custom values
|
|
*
|
|
* @deprecated 1.5.0
|
|
* @deprecated use WPSEO_Meta::get_value()
|
|
* @see WPSEO_Meta::get_value()
|
|
*
|
|
* @param string $val internal name of the value to get
|
|
* @param int $postid post ID of the post to get the value for
|
|
* @return string
|
|
*/
|
|
function wpseo_get_value( $val, $postid = 0 ) {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.0', 'WPSEO_Meta::get_value()' );
|
|
return WPSEO_Meta::get_value( $val, $postid );
|
|
}
|
|
|
|
|
|
/**
|
|
* Save a custom meta value
|
|
*
|
|
* @deprecated 1.5.0
|
|
* @deprecated use WPSEO_Meta::set_value() or just use update_post_meta()
|
|
* @see WPSEO_Meta::set_value()
|
|
*
|
|
* @param string $meta_key the meta to change
|
|
* @param mixed $meta_value the value to set the meta to
|
|
* @param int $post_id the ID of the post to change the meta for.
|
|
* @return bool whether the value was changed
|
|
*/
|
|
function wpseo_set_value( $meta_key, $meta_value, $post_id ) {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.0', 'WPSEO_Meta::set_value()' );
|
|
return WPSEO_Meta::set_value( $meta_key, $meta_value, $post_id );
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve an array of all the options the plugin uses. It can't use only one due to limitations of the options API.
|
|
*
|
|
* @deprecated 1.5.0
|
|
* @deprecated use WPSEO_Options::get_option_names()
|
|
* @see WPSEO_Options::get_option_names()
|
|
*
|
|
* @return array of options.
|
|
*/
|
|
function get_wpseo_options_arr() {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.0', 'WPSEO_Options::get_option_names()' );
|
|
return WPSEO_Options::get_option_names();
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve all the options for the SEO plugin in one go.
|
|
*
|
|
* @deprecated 1.5.0
|
|
* @deprecated use WPSEO_Options::get_all()
|
|
* @see WPSEO_Options::get_all()
|
|
*
|
|
* @return array of options
|
|
*/
|
|
function get_wpseo_options() {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.0', 'WPSEO_Options::get_all()' );
|
|
return WPSEO_Options::get_all();
|
|
}
|
|
|
|
/**
|
|
* Used for imports, both in dashboard and import settings pages, this functions either copies
|
|
* $old_metakey into $new_metakey or just plain replaces $old_metakey with $new_metakey
|
|
*
|
|
* @deprecated 1.5.0
|
|
* @deprecated use WPSEO_Meta::replace_meta()
|
|
* @see WPSEO_Meta::replace_meta()
|
|
*
|
|
* @param string $old_metakey The old name of the meta value.
|
|
* @param string $new_metakey The new name of the meta value, usually the WP SEO name.
|
|
* @param bool $replace Whether to replace or to copy the values.
|
|
*/
|
|
function replace_meta( $old_metakey, $new_metakey, $replace = false ) {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.0', 'WPSEO_Meta::replace_meta()' );
|
|
WPSEO_Meta::replace_meta( $old_metakey, $new_metakey, $replace );
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieve a taxonomy term's meta value.
|
|
*
|
|
* @deprecated 1.5.0
|
|
* @deprecated use WPSEO_Taxonomy_Meta::get_term_meta()
|
|
* @see WPSEO_Taxonomy_Meta::get_term_meta()
|
|
*
|
|
* @param string|object $term term to get the meta value for
|
|
* @param string $taxonomy name of the taxonomy to which the term is attached
|
|
* @param string $meta meta value to get
|
|
* @return bool|mixed value when the meta exists, false when it does not
|
|
*/
|
|
function wpseo_get_term_meta( $term, $taxonomy, $meta ) {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.0', 'WPSEO_Taxonomy_Meta::get_term_meta' );
|
|
WPSEO_Taxonomy_Meta::get_term_meta( $term, $taxonomy, $meta );
|
|
}
|
|
|
|
/**
|
|
* Throw a notice about an invalid custom taxonomy used
|
|
*
|
|
* @since 1.4.14
|
|
* @deprecated 1.5.4 (removed)
|
|
*/
|
|
function wpseo_invalid_custom_taxonomy() {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.4' );
|
|
}
|
|
|
|
/**
|
|
* Retrieve a post's terms, comma delimited.
|
|
*
|
|
* @deprecated 1.5.4
|
|
* @deprecated use WPSEO_Replace_Vars::get_terms()
|
|
* @see WPSEO_Replace_Vars::get_terms()
|
|
*
|
|
* @param int $id ID of the post to get the terms for.
|
|
* @param string $taxonomy The taxonomy to get the terms for this post from.
|
|
* @param bool $return_single If true, return the first term.
|
|
* @return string either a single term or a comma delimited string of terms.
|
|
*/
|
|
function wpseo_get_terms( $id, $taxonomy, $return_single = false ) {
|
|
_deprecated_function( __FUNCTION__, 'WPSEO 1.5.4', 'WPSEO_Replace_Vars::get_terms' );
|
|
$replacer = new WPSEO_Replace_Vars;
|
|
return $replacer->get_terms( $id, $taxonomy, $return_single );
|
|
}
|