feat: initial ACRIB WordPress deployment

- WordPress 6.9.4 (es_ES) with Kadence theme
- Homepage: Hero, La Asociación, Pilares, Beneficios, Eventos, Miembros, Hazte Miembro, Contacto
- Brand identity: #13294b navy, #a12932 burgundy, #c69c48 gold
- Fonts: Raleway (headings) + Source Sans 3 (body) + Lato (UI)
- Plugins: Kadence Blocks, Polylang, Contact Form 7
- Custom CSS with full brand styling and responsive layout
- HTTPS enforced via wp-config.php proxy detection
This commit is contained in:
Malin
2026-05-19 19:25:59 +02:00
commit f3ff7b7186
6119 changed files with 1984255 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Aqua Resizer when used in themes.
*
* @since 2.8
*/
class PLL_Aqua_Resizer {
/**
* Setups filters.
*
* @since 2.8
*/
public function init() {
add_filter( 'pll_home_url_black_list', array( $this, 'home_url_black_list' ) );
}
/**
* Avoids filtering the home url for the function aq_resize().
*
* @since 1.1.5
*
* @param array $arr Home url filter black list.
* @return array
*/
public function home_url_black_list( $arr ) {
return array_merge( $arr, array( array( 'function' => 'aq_resize' ) ) );
}
}

View File

@@ -0,0 +1,13 @@
<?php
/**
* Loads the integration with Aqua Resizer.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
PLL_Integrations::instance()->aq_resizer = new PLL_Aqua_Resizer();
PLL_Integrations::instance()->aq_resizer->init();

View File

@@ -0,0 +1,108 @@
<?php
/**
* @package Polylang
*/
/**
* A class to manage specific compatibility issue with cache plugins
* Tested with WP Rocket 2.10.7
*
* @since 2.3
*/
class PLL_Cache_Compat {
/**
* Setups actions
*
* @since 2.3
*/
public function init() {
if ( PLL_COOKIE ) {
add_action( 'wp_enqueue_scripts', array( $this, 'add_cookie_script' ) );
}
// Since version 3.0.5, WP Rocket does not serve the cached page if our cookie is not set
if ( ! defined( 'WP_ROCKET_VERSION' ) || version_compare( WP_ROCKET_VERSION, '3.0.5', '<' ) ) {
add_action( 'wp', array( $this, 'do_not_cache_site_home' ) );
}
add_action( 'clean_post_cache', array( $this, 'clean_post_cache' ), 1 );
}
/**
* Currently all tested cache plugins don't send cookies with cached pages.
* This makes us impossible to know the language of the last browsed page.
* This functions allows to create the cookie in javascript as a workaround.
*
* @since 2.3
*
* @return void
*/
public function add_cookie_script() {
// Embeds should not set the cookie.
if ( is_embed() ) {
return;
}
$domain = ( 2 === PLL()->options['force_lang'] ) ? wp_parse_url( PLL()->links_model->home, PHP_URL_HOST ) : COOKIE_DOMAIN;
$samesite = ( 3 === PLL()->options['force_lang'] ) ? 'None' : 'Lax';
/** This filter is documented in src/cookie.php */
$expiration = (int) apply_filters( 'pll_cookie_expiration', YEAR_IN_SECONDS );
if ( 0 !== $expiration ) {
$format = 'var expirationDate = new Date();
expirationDate.setTime( expirationDate.getTime() + %7$d * 1000 );
document.cookie = "%1$s=%2$s; expires=" + expirationDate.toUTCString() + "; path=%3$s%4$s%5$s%6$s";';
} else {
$format = 'document.cookie = "%1$s=%2$s; path=%3$s%4$s%5$s%6$s";';
}
$js = sprintf(
"(function() {
{$format}
}());\n",
esc_js( PLL_COOKIE ),
esc_js( pll_current_language() ),
esc_js( COOKIEPATH ),
$domain ? '; domain=' . esc_js( $domain ) : '',
is_ssl() ? '; secure' : '',
'; SameSite=' . $samesite,
esc_js( $expiration )
);
// Need to register prior to enqueue empty script and add extra code to it.
wp_register_script( 'pll_cookie_script', '', array(), POLYLANG_VERSION, true );
wp_enqueue_script( 'pll_cookie_script' );
wp_add_inline_script( 'pll_cookie_script', $js );
}
/**
* Informs cache plugins not to cache the home in the default language
* When the detection of the browser preferred language is active
*
* @since 2.3
*/
public function do_not_cache_site_home() {
if ( ! defined( 'DONOTCACHEPAGE' ) && PLL()->options['browser'] && PLL()->options['hide_default'] && is_front_page() && pll_current_language() === pll_default_language() ) {
define( 'DONOTCACHEPAGE', true );
}
}
/**
* Allows cache plugins to clean the right post type archive cache when cleaning a post cache.
*
* @since 3.0.5
*
* @param int $post_id Post id.
*/
public function clean_post_cache( $post_id ) {
$lang = PLL()->model->post->get_language( $post_id );
if ( $lang ) {
$filter_callback = function ( $link, $post_type ) use ( $lang ) {
return pll_is_translated_post_type( $post_type ) && 'post' !== $post_type ? PLL()->links_model->switch_language_in_link( $link, $lang ) : $link;
};
add_filter( 'post_type_archive_link', $filter_callback, 99, 2 );
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Loads the integration with cache plugins.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( pll_is_cache_active() ) {
add_action( 'pll_init', array( PLL_Integrations::instance()->cache_compat = new PLL_Cache_Compat(), 'init' ) );
}
},
0
);

View File

@@ -0,0 +1,35 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Custom Field Template.
*
* @since 2.8
*/
class PLL_Cft {
/**
* Setups actions.
*
* @since 2.8
*/
public function init() {
add_action( 'add_meta_boxes', array( $this, 'cft_copy' ), 10, 2 );
}
/**
* Custom field template does check $_REQUEST['post'] to populate the custom fields values.
*
* @since 1.0.2
*
* @param string $post_type Unused.
* @param WP_Post $post Current post object.
*/
public function cft_copy( $post_type, $post ) {
global $custom_field_template;
if ( isset( $custom_field_template, $_REQUEST['from_post'], $_REQUEST['new_lang'] ) && ! empty( $post ) ) { // phpcs:ignore WordPress.Security.NonceVerification
$_REQUEST['post'] = $post->ID;
}
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Loads the integration with Custom Field Template.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( class_exists( 'custom_field_template' ) ) {
PLL_Integrations::instance()->cft = new PLL_Cft();
PLL_Integrations::instance()->cft->init();
}
},
0
);

View File

@@ -0,0 +1,81 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with WordPress MU Domain Mapping.
*
* @since 2.8
*/
class PLL_Domain_Mapping {
/**
* Setups actions.
*
* @since 2.8
*/
public function __construct() {
if ( function_exists( 'redirect_to_mapped_domain' ) ) {
$options = get_option( 'polylang' );
if ( is_array( $options ) && $options['force_lang'] < 2 ) {
pll_set_constant( 'PLL_CACHE_HOME_URL', false );
}
if ( ! get_site_option( 'dm_no_primary_domain' ) ) {
remove_action( 'template_redirect', 'redirect_to_mapped_domain' );
add_action( 'template_redirect', array( $this, 'dm_redirect_to_mapped_domain' ) );
}
}
}
/**
* Fix primary domain check which forces only one domain per blog.
* Accept only known domains/subdomains for the current blog.
*
* @since 2.2
*/
public function dm_redirect_to_mapped_domain() {
// Don't go further if we stopped loading the plugin early (for example when deactivate-polylang=1).
if ( ! function_exists( 'PLL' ) ) {
// Rely on MU Domain Mapping.
redirect_to_mapped_domain();
}
// The language is set from the subdomain or domain name
if ( PLL()->options['force_lang'] > 1 ) {
// Don't redirect the main site
if ( is_main_site() ) {
return;
}
// Don't redirect post previews
if ( isset( $_GET['preview'] ) && 'true' === $_GET['preview'] ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}
// Don't redirect theme customizer
if ( isset( $_POST['customize'] ) && isset( $_POST['theme'] ) && 'on' === $_POST['customize'] ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}
// If we can't associate the requested domain to a language, redirect to the default domain
$requested_url = pll_get_requested_url();
$requested_host = wp_parse_url( $requested_url, PHP_URL_HOST );
$hosts = PLL()->links_model->get_hosts();
$lang = array_search( $requested_host, $hosts );
if ( empty( $lang ) ) {
$status = get_site_option( 'dm_301_redirect' ) ? '301' : '302'; // Honor status redirect option
$redirect = str_replace( '://' . $requested_host, '://' . $hosts[ PLL()->options['default_lang'] ], $requested_url );
wp_safe_redirect( $redirect, $status );
exit;
}
} else {
// Otherwise rely on MU Domain Mapping
redirect_to_mapped_domain();
}
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Loads the integration with WordPress MU Domain Mapping.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
PLL_Integrations::instance()->dm = new PLL_Domain_Mapping();

View File

@@ -0,0 +1,37 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Duplicate Post.
*
* @since 2.8
*/
class PLL_Duplicate_Post {
/**
* Setups actions.
*
* @since 2.8
*/
public function init() {
add_filter( 'option_duplicate_post_taxonomies_blacklist', array( $this, 'taxonomies_blacklist' ) );
}
/**
* Avoid duplicating the 'post_translations' taxonomy.
*
* @since 1.8
*
* @param array|string $taxonomies The list of taxonomies not to duplicate.
* @return array
*/
public function taxonomies_blacklist( $taxonomies ) {
if ( empty( $taxonomies ) ) {
$taxonomies = array(); // As we get an empty string when there is no taxonomy.
}
$taxonomies[] = 'post_translations';
return $taxonomies;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Loads the integration with Duplicate Post.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( defined( 'DUPLICATE_POST_CURRENT_VERSION' ) ) {
PLL_Integrations::instance()->duplicate_post = new PLL_Duplicate_Post();
PLL_Integrations::instance()->duplicate_post->init();
}
},
0
);

View File

@@ -0,0 +1,20 @@
<?php
/**
* /!\ DO NOT DIRECTLY EDIT THIS FILE, THIS FILE IS AUTO-GENERATED AS PART OF THE BUILD PROCESS.
*/
return array(
'aqua-resizer',
'cache',
'custom-field-template',
'domain-mapping',
'duplicate-post',
'jetpack',
'no-category-base',
'twenty-seventeen',
'wp-importer',
'wp-offload-media',
'wp-sweep',
'wpseo',
'yarpp',
);

View File

@@ -0,0 +1,61 @@
<?php
/**
* @package Polylang
*/
/**
* Container for 3rd party plugins ( and themes ) integrations.
* This class is available as soon as the plugin is loaded.
*
* @since 1.0
* @since 2.8 Renamed from PLL_Plugins_Compat to PLL_Integrations.
*/
#[AllowDynamicProperties]
class PLL_Integrations {
/**
* Singleton instance.
*
* @var PLL_Integrations|null
*/
protected static $instance = null;
/**
* Constructor.
*
* @since 1.0
*/
protected function __construct() {}
/**
* Returns the single instance of the class.
*
* @since 1.7
*
* @return self
*/
public static function instance(): self {
if ( null === self::$instance ) {
self::$instance = new self();
self::$instance->init();
}
return self::$instance;
}
/**
* Requires integrations.
*
* @since 3.7
*
* @return void
*/
protected function init(): void {
$load_scripts = require __DIR__ . '/integration-build.php';
foreach ( $load_scripts as $load_script ) {
require_once __DIR__ . "/{$load_script}/load.php";
}
}
}
class_alias( 'PLL_Integrations', 'PLL_Plugins_Compat' ); // For Backward compatibility.

View File

@@ -0,0 +1,121 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with the Jetpack Twenty Fourteenn Featured content
*
* @since 2.4
*/
class PLL_Featured_Content {
/**
* Constructor
*
* @since 2.6
*/
public function init() {
add_filter( 'transient_featured_content_ids', array( $this, 'featured_content_ids' ) );
add_filter( 'option_featured-content', array( $this, 'option_featured_content' ) );
}
/**
* Tell whether the theme supports the featured content
*
* @since 2.4
*
* @return bool
*/
protected function is_active() {
return 'twentyfourteen' === get_template() || ( defined( 'JETPACK__VERSION' ) && get_theme_support( 'featured-content' ) );
}
/**
* Get the theme featured posts filter name
*
* @since 2.4
*
* @return string
*/
protected function get_featured_posts_filter() {
$theme_support = get_theme_support( 'featured-content' );
if ( isset( $theme_support[0]['featured_content_filter'] ) ) {
$theme_support[0]['filter'] = $theme_support[0]['featured_content_filter'];
unset( $theme_support[0]['featured_content_filter'] );
}
return $theme_support[0]['filter'];
}
/**
* Rewrites the function Featured_Content::get_featured_post_ids()
*
* @since 1.4
*
* @param array $featured_ids Featured posts ids
* @return array modified featured posts ids ( include all languages )
*/
public function featured_content_ids( $featured_ids ) {
if ( ! $this->is_active() || false !== $featured_ids ) {
return $featured_ids;
}
$settings = Featured_Content::get_setting();
if ( ! $term = get_term_by( 'name', $settings['tag-name'], 'post_tag' ) ) {
return $featured_ids;
}
// Get featured tag translations
$tags = PLL()->model->term->get_translations( $term->term_id );
$ids = array();
// Query for featured posts in all languages
// One query per language to get the correct number of posts per language
foreach ( $tags as $tag ) {
$args = array(
'lang' => 0, // Avoid language filters.
'fields' => 'ids',
'numberposts' => Featured_Content::$max_posts,
'tax_query' => array(
array(
'taxonomy' => 'post_tag',
'terms' => (int) $tag,
),
),
);
// Available in Jetpack, but not in Twenty Fourteen.
if ( isset( Featured_Content::$post_types ) ) {
$args['post_type'] = Featured_Content::$post_types;
}
$_ids = get_posts( $args );
$ids = array_merge( $ids, $_ids );
}
$ids = array_map( 'absint', $ids );
set_transient( 'featured_content_ids', $ids );
return $ids;
}
/**
* Translates the featured tag id in featured content settings
* Mainly to allow hiding it when requested in featured content options
* Acts only on frontend
*
* @since 1.4
*
* @param array $settings featured content settings
* @return array modified $settings
*/
public function option_featured_content( $settings ) {
if ( $this->is_active() && PLL() instanceof PLL_Frontend && $settings['tag-id'] && $tr = pll_get_term( $settings['tag-id'] ) ) {
$settings['tag-id'] = $tr;
}
return $settings;
}
}

View File

@@ -0,0 +1,137 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Jetpack.
*
* @since 2.3
*/
class PLL_Jetpack {
/**
* Constructor.
*
* @since 2.3
*/
public function __construct() {
add_action( 'init', array( $this, 'jetpack_init' ) );
add_action( 'jetpack_widget_get_top_posts', array( $this, 'jetpack_widget_get_top_posts' ) );
add_filter( 'grunion_contact_form_field_html', array( $this, 'grunion_contact_form_field_html_filter' ), 10, 2 );
add_filter( 'jetpack_open_graph_tags', array( $this, 'jetpack_ogp' ) );
add_filter( 'jetpack_relatedposts_filter_filters', array( $this, 'jetpack_relatedposts_filter_filters' ), 10, 2 );
// Jetpack infinite scroll.
if ( isset( $_GET['infinity'], $_POST['action'] ) && 'infinite_scroll' == $_POST['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
add_filter( 'pll_is_ajax_on_front', '__return_true' );
}
}
/**
* Add filters
*
* @since 2.1
*/
public function jetpack_init() {
if ( ! defined( 'JETPACK__VERSION' ) ) {
return;
}
// Infinite scroll ajax url must be on the right domain.
if ( did_action( 'pll_init' ) && PLL()->options['force_lang'] > 1 ) {
add_filter( 'infinite_scroll_ajax_url', array( PLL()->links_model, 'site_url' ) );
add_filter( 'infinite_scroll_js_settings', array( $this, 'jetpack_infinite_scroll_js_settings' ) );
}
}
/**
* Filter the Top Posts and Pages by language.
* Adapted from the same function in jetpack-3.0.2/3rd-party/wpml.php
*
* @since 1.5.4
*
* @param array $posts Array of the most popular posts.
* @return array
*/
public function jetpack_widget_get_top_posts( $posts ) {
foreach ( $posts as $k => $post ) {
if ( pll_current_language() !== pll_get_post_language( $post['post_id'] ) ) {
unset( $posts[ $k ] );
}
}
return $posts;
}
/**
* Filter the HTML of the Contact Form and output the one requested by language.
* Adapted from the same function in jetpack-3.0.2/3rd-party/wpml.php
* Keeps using 'icl_translate' as the function registers the string.
*
* @since 1.5.4
*
* @param string $r Contact Form HTML output.
* @param string $field_label Field label.
* @return string
*/
public function grunion_contact_form_field_html_filter( $r, $field_label ) {
if ( function_exists( 'icl_translate' ) ) {
if ( pll_current_language() !== pll_default_language() ) {
$label_translation = icl_translate( 'jetpack ', $field_label . '_label', $field_label );
$r = str_replace( $field_label, $label_translation, $r );
}
}
return $r;
}
/**
* Adds opengraph support for locale and translations.
*
* @since 1.6
*
* @param array $tags Opengraph tags to output.
* @return array
*/
public function jetpack_ogp( $tags ) {
if ( did_action( 'pll_init' ) ) {
foreach ( PLL()->model->get_languages_list() as $language ) {
if ( PLL()->curlang->slug !== $language->slug && PLL()->links->get_translation_url( $language ) && isset( $language->facebook ) ) {
$tags['og:locale:alternate'][] = $language->facebook;
}
if ( PLL()->curlang->slug === $language->slug && isset( $language->facebook ) ) {
$tags['og:locale'] = $language->facebook;
}
}
}
return $tags;
}
/**
* Allows to make sure that related posts are in the correct language.
*
* @since 1.8
*
* @param array $filters Array of ElasticSearch filters based on the post_id and args.
* @param string $post_id Post ID of the post for which we are retrieving Related Posts.
* @return array
*/
public function jetpack_relatedposts_filter_filters( $filters, $post_id ) {
$slug = sanitize_title( pll_get_post_language( $post_id, 'slug' ) );
$filters[] = array( 'term' => array( 'taxonomy.language.slug' => $slug ) );
return $filters;
}
/**
* Fixes the settings history host for infinite scroll when using subdomains or multiple domains.
*
* @since 2.1
*
* @param array $settings Infinite scroll JS settings outputted in the head.
* @return array
*/
public function jetpack_infinite_scroll_js_settings( $settings ) {
$settings['history']['host'] = wp_parse_url( pll_home_url(), PHP_URL_HOST ); // Jetpack uses get_option( 'home' ).
return $settings;
}
}

View File

@@ -0,0 +1,14 @@
<?php
/**
* Loads the integration with Jetpack.
* Works for Twenty Fourteen featured content too.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
PLL_Integrations::instance()->jetpack = new PLL_Jetpack(); // Must be loaded before the plugin is active.
add_action( 'pll_init', array( PLL_Integrations::instance()->featured_content = new PLL_Featured_Content(), 'init' ) );

View File

@@ -0,0 +1,13 @@
<?php
/**
* Loads the integration with No Category Base.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
PLL_Integrations::instance()->no_category_base = new PLL_No_Category_Base();
PLL_Integrations::instance()->no_category_base->init();

View File

@@ -0,0 +1,36 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with No Category Base.
* Works for Yoast SEO too.
*
* @since 2.8
*/
class PLL_No_Category_Base {
/**
* Setups actions.
*
* @since 2.8
*/
public function init() {
add_filter( 'get_terms_args', array( $this, 'no_category_base_get_terms_args' ), 5 ); // Before adding our cache domain.
}
/**
* Make sure No category base plugins get all the categories when flushing rules.
*
* @since 2.1
*
* @param array $args WP_Term_Query arguments.
* @return array
*/
public function no_category_base_get_terms_args( $args ) {
if ( doing_filter( 'category_rewrite_rules' ) ) {
$args['lang'] = '';
}
return $args;
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Loads the integration with WordPress MU Domain Mapping.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action( 'init', array( PLL_Integrations::instance()->twenty_seventeen = new PLL_Twenty_Seventeen(), 'init' ) );

View File

@@ -0,0 +1,30 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Twenty_Seventeen.
*
* @since 2.8
*/
class PLL_Twenty_Seventeen {
/**
* Translates the front page panels and the header video.
*
* @since 2.0.10
*/
public function init() {
if ( 'twentyseventeen' === get_template() && did_action( 'pll_init' ) ) {
if ( function_exists( 'twentyseventeen_panel_count' ) && PLL() instanceof PLL_Frontend ) {
$num_sections = twentyseventeen_panel_count();
for ( $i = 1; $i < ( 1 + $num_sections ); $i++ ) {
add_filter( 'theme_mod_panel_' . $i, 'pll_get_post' );
}
}
$theme_slug = get_option( 'stylesheet' ); // In case we are using a child theme.
new PLL_Translate_Option( "theme_mods_$theme_slug", array( 'external_header_video' => 1 ), array( 'context' => 'Twenty Seventeen' ) );
}
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Loads the integration with WordPress Importer.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
PLL_Integrations::instance()->wp_importer = new PLL_WordPress_Importer();

View File

@@ -0,0 +1,70 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with WordPress Importer.
*
* @since 2.8
*/
class PLL_WordPress_Importer {
/**
* Setups filters.
*
* @since 2.8
*/
public function __construct() {
add_action( 'init', array( $this, 'maybe_wordpress_importer' ) );
add_filter( 'wp_import_terms', array( $this, 'wp_import_terms' ) );
}
/**
* If WordPress Importer is active, replace the wordpress_importer_init function.
*
* @since 1.2
*/
public function maybe_wordpress_importer() {
if ( defined( 'WP_LOAD_IMPORTERS' ) && class_exists( 'WP_Import' ) ) {
remove_action( 'admin_init', 'wordpress_importer_init' );
add_action( 'admin_init', array( $this, 'wordpress_importer_init' ) );
}
}
/**
* Loads our child class PLL_WP_Import instead of WP_Import.
*
* @since 1.2
*/
public function wordpress_importer_init() {
$class = new ReflectionClass( 'WP_Import' );
load_plugin_textdomain( 'wordpress-importer', false, basename( dirname( $class->getFileName() ) ) . '/languages' );
$GLOBALS['wp_import'] = new PLL_WP_Import();
register_importer( 'wordpress', 'WordPress', __( 'Import <strong>posts, pages, comments, custom fields, categories, and tags</strong> from a WordPress export file.', 'polylang' ), array( $GLOBALS['wp_import'], 'dispatch' ) ); // phpcs:ignore WordPress.WP.CapitalPDangit.MisspelledInText
}
/**
* Sets the flag when importing a language and the file has been exported with Polylang < 1.8.
*
* @since 1.8
*
* @param array $terms An array of arrays containing terms information form the WXR file.
* @return array
*/
public function wp_import_terms( $terms ) {
$languages = include POLYLANG_DIR . '/src/settings/languages.php';
foreach ( $terms as $key => $term ) {
if ( 'language' === $term['term_taxonomy'] ) {
$description = maybe_unserialize( $term['term_description'] );
if ( empty( $description['flag_code'] ) && isset( $languages[ $description['locale'] ] ) ) {
$description['flag_code'] = $languages[ $description['locale'] ]['flag'];
$terms[ $key ]['term_description'] = maybe_serialize( $description );
}
}
}
return $terms;
}
}

View File

@@ -0,0 +1,231 @@
<?php
/**
* @package Polylang
*/
/**
* A class to import languages and translations information form a WXR file
*
* @since 1.2
*/
class PLL_WP_Import extends WP_Import {
/**
* Stores post_translations terms.
*
* @var array
*/
public $post_translations = array();
/**
* Overrides WP_Import::process_terms to remap terms translations.
*
* @since 1.2
*/
public function process_terms() {
$term_translations = array();
$term_languages = array();
// Store this for future usage as parent function unsets $this->terms.
foreach ( $this->terms as $term ) {
if ( 'post_translations' == $term['term_taxonomy'] ) {
$this->post_translations[] = $term;
}
if ( 'term_translations' == $term['term_taxonomy'] ) {
$term_translations[] = $term;
}
if ( 'language' === $term['term_taxonomy'] ) {
$term_languages[] = $term;
}
}
parent::process_terms();
// First reset the core terms cache as WordPress Importer calls wp_suspend_cache_invalidation( true );
wp_cache_set_terms_last_changed();
// Assign the default language in case the importer created the first language.
if ( empty( PLL()->options['default_lang'] ) ) {
$languages = get_terms( array( 'taxonomy' => 'language', 'hide_empty' => false, 'orderby' => 'term_id' ) );
$default_lang = reset( $languages );
PLL()->options['default_lang'] = $default_lang->slug;
}
/*
* Merge strings translations for an already existing language.
*
* Term metas are handled by the importer when creating a term,
* but not when updating an existing term.
*/
foreach ( $term_languages as $term ) {
if ( empty( $this->processed_terms[ $term['term_id'] ] ) || empty( $term['termmeta'] ) ) {
continue;
}
foreach ( $term['termmeta'] as $term_meta ) {
if ( '_pll_strings_translations' !== $term_meta['key'] ) {
continue;
}
$language = PLL()->model->languages->get( $term['term_id'] );
if ( empty( $language ) ) {
continue;
}
$strings = maybe_unserialize( $term_meta['value'] );
$mo = new PLL_MO();
$mo->import_from_db( $language );
foreach ( $strings as $msg ) {
$mo->add_entry_or_merge( $mo->make_entry( $msg[0], $msg[1] ) );
}
$mo->export_to_db( $language );
}
}
// Clean languages cache in case some of them were created during import.
PLL()->model->languages->clean_cache();
$this->remap_terms_relations( $term_translations );
$this->remap_translations( $term_translations, $this->processed_terms );
}
/**
* Overrides WP_Import::process_post to remap posts translations
* Also merges strings translations from the WXR file to the existing ones
*
* @since 1.2
*/
public function process_posts() {
$menu_items = array();
// Store this for future usage as parent function unset $this->posts
foreach ( $this->posts as $post ) {
if ( 'nav_menu_item' == $post['post_type'] ) {
$menu_items[] = $post;
}
}
parent::process_posts();
PLL()->model->languages->clean_cache(); // To update the posts count in (cached) languages list.
$this->remap_translations( $this->post_translations, $this->processed_posts );
unset( $this->post_translations );
// Language switcher menu items
foreach ( $menu_items as $item ) {
foreach ( $item['postmeta'] as $meta ) {
if ( '_pll_menu_item' == $meta['key'] ) {
update_post_meta( $this->processed_menu_items[ $item['post_id'] ], '_pll_menu_item', maybe_unserialize( $meta['value'] ) );
}
}
}
}
/**
* Remaps terms languages.
*
* @since 1.2
*
* @param array $terms array of terms in 'term_translations' taxonomy.
*/
protected function remap_terms_relations( &$terms ) {
global $wpdb;
$term_relationships = array();
foreach ( $terms as $term ) {
$translations = maybe_unserialize( $term['term_description'] );
foreach ( $translations as $slug => $old_id ) {
if ( $old_id && ! empty( $this->processed_terms[ $old_id ] ) && $lang = PLL()->model->get_language( $slug ) ) {
// Language relationship.
$term_relationships[] = array( $this->processed_terms[ $old_id ], $lang->get_tax_prop( 'term_language', 'term_taxonomy_id' ) );
// Translation relationship.
$term_relationships[] = array( $this->processed_terms[ $old_id ], get_term( $this->processed_terms[ $term['term_id'] ], 'term_translations' )->term_taxonomy_id );
}
}
}
// Insert term_relationships.
if ( ! empty( $term_relationships ) ) {
// Make sure we don't attempt to insert already existing term relationships.
$existing_term_relationships = $wpdb->get_results(
"SELECT tr.object_id, tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr
INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
WHERE tt.taxonomy IN ( 'term_language', 'term_translations' )"
);
foreach ( $existing_term_relationships as $key => $tr ) {
$existing_term_relationships[ $key ] = array( $tr->object_id, $tr->term_taxonomy_id );
}
$term_relationships = array_udiff(
$term_relationships,
$existing_term_relationships,
function ( $a, $b ) {
return strcmp( implode( ',', $a ), implode( ',', $b ) ); // An easy way to compare arrays (ok if values are int or numeric strings).
}
);
if ( ! empty( $term_relationships ) ) {
$wpdb->query(
$wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
sprintf(
"INSERT INTO {$wpdb->term_relationships} ( object_id, term_taxonomy_id ) VALUES %s",
implode( ',', array_fill( 0, count( $term_relationships ), '( %d, %d )' ) )
),
array_merge( ...$term_relationships )
)
);
}
}
}
/**
* Remaps translations for both posts and terms.
*
* @since 1.2
*
* @param array $terms Array of terms in 'post_translations' or 'term_translations' taxonomies?
* @param array $processed_objects Array of posts or terms processed by WordPress Importer.
*/
protected function remap_translations( &$terms, &$processed_objects ) {
global $wpdb;
$languages = pll_languages_list();
$to_update = array();
foreach ( $terms as $term ) {
$translations = maybe_unserialize( $term['term_description'] );
$new_translations = array();
foreach ( $translations as $slug => $old_id ) {
if ( in_array( $slug, $languages, true ) && $old_id && ! empty( $processed_objects[ $old_id ] ) ) {
$new_translations[ $slug ] = $processed_objects[ $old_id ];
} else {
$new_translations[ $slug ] = $old_id; // Preserve values for all keys which are not our language slugs.
}
}
if ( ! empty( $new_translations ) ) {
$to_update['case'][] = array( $this->processed_terms[ $term['term_id'] ], maybe_serialize( $new_translations ) );
$to_update['in'][] = (int) $this->processed_terms[ $term['term_id'] ];
}
}
if ( ! empty( $to_update ) ) {
$wpdb->query(
$wpdb->prepare(
sprintf(
"UPDATE {$wpdb->term_taxonomy}
SET description = ( CASE term_id %s END )
WHERE term_id IN (%s)",
implode( ' ', array_fill( 0, count( $to_update['case'] ), 'WHEN %d THEN %s' ) ),
implode( ',', array_fill( 0, count( $to_update['in'] ), '%d' ) )
),
array_merge( array_merge( ...$to_update['case'] ), $to_update['in'] )
)
);
}
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* @package Polylang
*/
/**
* A class to manage the integration with WP Offload Media Lite.
* Version tested: 2.1.1
*
* @since 2.6
*/
class PLL_AS3CF {
/**
* Stores if a media is translated when it is deleted.
*
* @var bool[]
*/
private $is_media_translated = array();
/**
* Initializes filters and actions.
*
* @since 2.6
*/
public function init() {
add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ) );
add_action( 'delete_attachment', array( $this, 'check_translated_media' ), 5 ); // Before Polylang deletes the translations information.
add_action( 'delete_attachment', array( $this, 'prevent_file_deletion' ), 15 ); // Between Polylang and WP Offload Media.
}
/**
* Synchronizes post metas
*
* @since 2.6
*
* @param array $metas List of custom fields names.
* @return array
*/
public function copy_post_metas( $metas ) {
$metas[] = 'amazonS3_info';
$metas[] = 'as3cf_filesize_total';
return $metas;
}
/**
* Checks if the deleted attachment was translated and stores the information.
*
* @since 2.6
*
* @param int $post_id Id of the attachment being deleted.
*/
public function check_translated_media( $post_id ) {
$this->is_media_translated[ $post_id ] = ( count( pll_get_post_translations( $post_id ) ) > 1 );
}
/**
* Deletes the WP Offload Media information from the attachment being deleted.
* That way WP Offload Media won't delete the file stored in the cloud.
* Done after Polylang has deleted the translations information, to avoid the synchronization of the deletion
* and of course before WP Offload Media deletes the file, normally at priority 20.
*
* @since 2.6
*
* @param int $post_id Id of the attachment being deleted.
*/
public function prevent_file_deletion( $post_id ) {
if ( ! empty( $this->is_media_translated[ $post_id ] ) ) {
delete_post_meta( $post_id, 'amazonS3_info' );
delete_post_meta( $post_id, 'as3cf_filesize_total' );
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Loads the integration with WP Offload Media Lite.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( function_exists( 'as3cf_init' ) && class_exists( 'PLL_AS3CF' ) ) {
add_action( 'pll_init', array( PLL_Integrations::instance()->as3cf = new PLL_AS3CF(), 'init' ) );
}
},
0
);

View File

@@ -0,0 +1,21 @@
<?php
/**
* Loads the integration with WP Sweep.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( defined( 'WP_SWEEP_VERSION' ) ) {
PLL_Integrations::instance()->wp_sweep = new PLL_WP_Sweep();
PLL_Integrations::instance()->wp_sweep->init();
}
},
0
);

View File

@@ -0,0 +1,62 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with WP Sweep.
*
* @since 2.8
*/
class PLL_WP_Sweep {
/**
* Setups actions.
*
* @since 2.8
*/
public function init() {
add_filter( 'wp_sweep_excluded_taxonomies', array( $this, 'wp_sweep_excluded_taxonomies' ) );
add_filter( 'wp_sweep_excluded_termids', array( $this, 'wp_sweep_excluded_termids' ), 0 );
}
/**
* Add 'term_language' and 'term_translations' to excluded taxonomies otherwise terms loose their language and translation group.
*
* @since 2.0
*
* @param array $excluded_taxonomies List of taxonomies excluded from sweeping.
* @return array
*/
public function wp_sweep_excluded_taxonomies( $excluded_taxonomies ) {
return array_merge( $excluded_taxonomies, array( 'term_language', 'term_translations' ) );
}
/**
* Add the translation of the default taxonomy terms and our language terms to the excluded terms.
*
* @since 2.9
*
* @param array $excluded_term_ids List of term ids excluded from sweeping.
* @return array
*/
public function wp_sweep_excluded_termids( $excluded_term_ids ) {
// We got a list of excluded terms (defaults and parents). Let exclude their translations too.
$_term_ids = array();
foreach ( $excluded_term_ids as $excluded_term_id ) {
$_term_ids = array_merge( $_term_ids, array_values( pll_get_term_translations( $excluded_term_id ) ) );
}
$excluded_term_ids = array_merge( $excluded_term_ids, $_term_ids );
// Add the terms of our languages.
foreach ( PLL()->model->get_languages_list() as $language ) {
$excluded_term_ids = array_merge(
$excluded_term_ids,
array_values( $language->get_tax_props( 'term_id' ) )
);
}
return array_unique( $excluded_term_ids );
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Loads the integration with Yoast SEO.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( defined( 'WPSEO_VERSION' ) ) {
add_action( 'pll_init', array( PLL_Integrations::instance()->wpseo = new PLL_WPSEO(), 'init' ) );
}
},
0
);

View File

@@ -0,0 +1,54 @@
<?php
/**
* @package Polylang
*/
use Yoast\WP\SEO\Presenters\Abstract_Indexable_Presenter;
/**
* Creates an Opengraph alternate locale meta tag to be consumed by Yoast SEO
* Requires Yoast SEO 14.0 or newer.
*
* @since 2.7.3
*/
final class PLL_WPSEO_OGP extends Abstract_Indexable_Presenter {
/**
* Facebook locale
*
* @var string $locale
*/
private $locale;
/**
* Constructor
*
* @since 2.7.3
*
* @param string $locale Facebook locale.
*/
public function __construct( $locale ) {
$this->locale = $locale;
}
/**
* Returns the meta Opengraph alternate locale meta tag
*
* @since 2.7.3
*
* @return string
*/
public function present() {
return sprintf( '<meta property="og:locale:alternate" content="%s" />', esc_attr( $this->get() ) );
}
/**
* Returns the alternate locale
*
* @since 2.7.3
*
* @return string
*/
public function get() {
return $this->locale;
}
}

View File

@@ -0,0 +1,517 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Yoast SEO
* Version tested: 15.9.2
*
* @since 2.3
*/
class PLL_WPSEO {
/**
* Translate options and add specific filters and actions
*
* @since 1.6.4
*/
public function init() {
add_action( 'wp_loaded', array( $this, 'wpseo_translate_options' ) );
add_filter( 'wpseo_dynamic_permalinks_enabled', '__return_true', 999 );
if ( PLL() instanceof PLL_Frontend ) {
// Filters sitemap queries to remove inactive language or to get
// one sitemap per language when using multiple domains or subdomains
// because WPSEO does not accept several domains or subdomains in one sitemap
add_filter( 'wpseo_posts_join', array( $this, 'wpseo_posts_join' ), 10, 2 );
add_filter( 'wpseo_posts_where', array( $this, 'wpseo_posts_where' ), 10, 2 );
add_filter( 'wpseo_typecount_join', array( $this, 'wpseo_posts_join' ), 10, 2 );
add_filter( 'wpseo_typecount_where', array( $this, 'wpseo_posts_where' ), 10, 2 );
if ( PLL()->options['force_lang'] > 1 ) {
add_filter( 'wpseo_enable_xml_sitemap_transient_caching', '__return_false' ); // Disable cache! otherwise WPSEO keeps only one domain (thanks to Junaid Bhura)
add_filter( 'home_url', array( $this, 'wpseo_home_url' ), 10, 2 ); // Fix home_url
add_action( 'setup_theme', array( $this, 'maybe_deactivate_sitemap' ) ); // Deactivate sitemaps for inactive languages.
} else {
// Get all terms in all languages when the language is set from the content or directory name
add_filter( 'get_terms_args', array( $this, 'wpseo_remove_terms_filter' ) );
add_action( 'pre_get_posts', array( $this, 'before_sitemap' ), 0 ); // Needs to be fired before WPSEO_Sitemaps::redirect()
}
add_filter( 'pll_home_url_white_list', array( $this, 'wpseo_home_url_white_list' ) );
add_filter( 'wpseo_frontend_presenters', array( $this, 'wpseo_frontend_presenters' ) );
add_filter( 'wpseo_canonical', array( $this, 'wpseo_canonical' ) );
add_filter( 'wpseo_frontend_presentation', array( $this, 'frontend_presentation' ) );
add_filter( 'wpseo_breadcrumb_indexables', array( $this, 'breadcrumb_indexables' ) );
} else {
add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ), 10, 4 );
add_filter( 'pll_translate_post_meta', array( $this, 'translate_post_meta' ), 10, 3 );
add_filter( 'pll_post_metas_to_export', array( $this, 'export_post_metas' ) );
// Yoast SEO adds the columns hooks only for the 'inline-save' action. We need them for 'pll_update_post_rows' too.
if ( wp_doing_ajax() && isset( $_POST['action'] ) && 'pll_update_post_rows' === $_POST['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
$GLOBALS['wpseo_meta_columns'] = new WPSEO_Meta_Columns();
}
}
}
/**
* Registers options for translation.
*
* @since 2.9
*/
public function wpseo_translate_options() {
if ( method_exists( 'WPSEO_Options', 'clear_cache' ) ) {
WPSEO_Options::clear_cache();
}
$keys = array(
'title-*',
'metadesc-*',
'bctitle-*',
'breadcrumbs-sep',
'breadcrumbs-home',
'breadcrumbs-prefix',
'breadcrumbs-archiveprefix',
'breadcrumbs-searchprefix',
'breadcrumbs-404crumb',
'company_name',
'rssbefore',
'rssafter',
'social-title-*',
'social-description-*',
);
new PLL_Translate_Option( 'wpseo_titles', array_fill_keys( $keys, 1 ), array( 'context' => 'wordpress-seo' ) );
$keys = array(
'og_frontpage_title',
'og_frontpage_desc',
);
new PLL_Translate_Option( 'wpseo_social', array_fill_keys( $keys, 1 ), array( 'context' => 'wordpress-seo' ) );
}
/**
* Fixes the home url as well as the stylesheet url,
* only when using multiple domains or subdomains.
*
* @since 1.6.4
*
* @param string $url The complete URL including scheme and path.
* @param string $path Path relative to the home URL.
* @return $url
*/
public function wpseo_home_url( $url, $path ) {
if ( empty( $path ) ) {
$path = ltrim( (string) wp_parse_url( pll_get_requested_url(), PHP_URL_PATH ), '/' );
}
if ( preg_match( '#sitemap(_index)?\.xml|([^\/]+?)-?sitemap([0-9]+)?\.xml|([a-z]+)?-?sitemap\.xsl#', $path ) ) {
$url = PLL()->links_model->switch_language_in_link( $url, PLL()->curlang );
}
return $url;
}
/**
* Get active languages for the sitemaps
*
* @since 2.0
*
* @return array list of active language slugs, empty if all languages are active
*/
protected function wpseo_get_active_languages() {
$languages = PLL()->model->get_languages_list();
if ( wp_list_filter( $languages, array( 'active' => false ) ) ) {
return wp_list_pluck( wp_list_filter( $languages, array( 'active' => false ), 'NOT' ), 'slug' );
}
return array();
}
/**
* Modifies the sql request for posts sitemaps.
*
* @since 1.6.4
*
* @param string $sql JOIN clause.
* @param string $post_type Post type.
* @return string
*/
public function wpseo_posts_join( $sql, $post_type ) {
return pll_is_translated_post_type( $post_type ) ? $sql . PLL()->model->post->join_clause() : $sql;
}
/**
* Modifies the sql request for posts sitemaps.
*
* @since 1.6.4
*
* @param string $sql WHERE clause.
* @param string $post_type Post type.
* @return string
*/
public function wpseo_posts_where( $sql, $post_type ) {
if ( ! pll_is_translated_post_type( $post_type ) ) {
return $sql;
}
if ( PLL()->options['force_lang'] > 1 && PLL()->curlang instanceof PLL_Language ) {
return $sql . PLL()->model->post->where_clause( PLL()->curlang );
}
$languages = $this->wpseo_get_active_languages();
if ( empty( $languages ) ) { // Empty when all languages are active.
$languages = pll_languages_list();
}
return $sql . PLL()->model->post->where_clause( $languages );
}
/**
* Removes the language filter (and remove inactive languages) for the taxonomy sitemaps
* Only when the language is set from the content or directory name
*
* @since 1.0.3
*
* @param array $args get_terms arguments
* @return array modified list of arguments
*/
public function wpseo_remove_terms_filter( $args ) {
if ( isset( $GLOBALS['wp_query']->query['sitemap'] ) ) {
$args['lang'] = implode( ',', $this->wpseo_get_active_languages() );
}
return $args;
}
/**
* Deactivates the sitemap for inactive languages when using subdomains or multiple domains
*
* @since 2.6.1
*/
public function maybe_deactivate_sitemap() {
global $wpseo_sitemaps;
if ( isset( $wpseo_sitemaps ) ) {
$active_languages = $this->wpseo_get_active_languages();
if ( ! empty( $active_languages ) && ! in_array( pll_current_language(), $active_languages ) ) {
remove_action( 'pre_get_posts', array( $wpseo_sitemaps, 'redirect' ), 1 );
}
}
}
/**
* Add filters before the sitemap is evaluated and outputted.
*
* @since 2.6
*
* @param WP_Query $query Instance of WP_Query being filtered.
*/
public function before_sitemap( $query ) {
$type = $query->get( 'sitemap' );
// Add the post post type archives in all languages to the sitemap
// Add the homepages for all languages to the sitemap when the front page displays posts
if ( $type && pll_is_translated_post_type( $type ) && ( 'post' !== $type || ! get_option( 'page_on_front' ) ) ) {
add_filter( "wpseo_sitemap_{$type}_content", array( $this, 'add_post_type_archive' ) );
}
}
/**
* Generates a post type archive sitemap url
*
* @since 2.6.1
*
* @param string $link The url.
* @param string $post_type The post type name.
* @return string Formatted sitemap url.
*/
protected function format_sitemap_url( $link, $post_type ) {
global $wpseo_sitemaps;
return $wpseo_sitemaps->renderer->sitemap_url(
array(
'loc' => $link,
'mod' => WPSEO_Sitemaps::get_last_modified_gmt( $post_type ),
'pri' => 1,
'chf' => 'daily',
)
);
}
/**
* Adds the home and post type archives urls for all (active) languages to the sitemap
*
* @since 2.6
*
* @param string $str additional urls to sitemap post
* @return string
*/
public function add_post_type_archive( $str ) {
$post_type = substr( substr( current_filter(), 14 ), 0, -8 );
$post_type_obj = get_post_type_object( $post_type );
$languages = wp_list_filter( PLL()->model->get_languages_list(), array( 'active' => false ), 'NOT' );
if ( 'post' === $post_type ) {
if ( ! empty( PLL()->options['hide_default'] ) ) {
// The home url is of course already added by WPSEO.
$languages = wp_list_filter( $languages, array( 'slug' => pll_default_language() ), 'NOT' );
}
foreach ( $languages as $lang ) {
$str .= $this->format_sitemap_url( pll_home_url( $lang->slug ), $post_type );
}
} elseif ( $post_type_obj->has_archive ) {
// Exclude cases where a post type archive is attached to a page (ex: WooCommerce).
$slug = ( true === $post_type_obj->has_archive ) ? $post_type_obj->rewrite['slug'] : $post_type_obj->has_archive;
if ( ! wpcom_vip_get_page_by_path( $slug ) ) {
// The post type archive in the current language is already added by WPSEO.
$languages = wp_list_filter( $languages, array( 'slug' => pll_current_language() ), 'NOT' );
foreach ( $languages as $lang ) {
PLL()->curlang = $lang; // Switch the language to get the correct archive link.
$link = get_post_type_archive_link( $post_type );
$str .= $this->format_sitemap_url( $link, $post_type );
}
}
}
return $str;
}
/**
* Filters the home url.
*
* @since 1.1.2
*
* @param array $arr The list of files or functions for which `home_url()` must be filtered.
* @return array
*/
public function wpseo_home_url_white_list( $arr ) {
return array_merge( $arr, array( array( 'file' => 'wordpress-seo' ) ) );
}
/**
* Get alternate language codes for Opengraph.
*
* @since 2.7.3
*
* @return string[]
*/
protected function get_ogp_alternate_languages() {
$alternates = array();
foreach ( PLL()->model->get_languages_list() as $language ) {
if ( isset( PLL()->curlang ) && PLL()->curlang->slug !== $language->slug && PLL()->links->get_translation_url( $language ) && isset( $language->facebook ) ) {
$alternates[] = $language->facebook;
}
}
// There is a risk that 2 languages have the same Facebook locale. So let's make sure to output each locale only once.
return array_unique( $alternates );
}
/**
* Adds opengraph support for translations
*
* @since 2.7.3
*
* @param array $presenters An array of objects implementing Abstract_Indexable_Presenter
* @return array
*/
public function wpseo_frontend_presenters( $presenters ) {
$_presenters = array();
foreach ( $presenters as $presenter ) {
$_presenters[] = $presenter;
if ( $presenter instanceof Yoast\WP\SEO\Presenters\Open_Graph\Locale_Presenter ) {
foreach ( $this->get_ogp_alternate_languages() as $lang ) {
$_presenters[] = new PLL_WPSEO_OGP( $lang );
}
}
}
return $_presenters;
}
/**
* Fixes the canonical front page url as unlike WP, WPSEO does not add a trailing slash to the canonical front page url.
*
* @since 1.7.10
*
* @param string $url The canonical URL evaluated by Yoast SEO.
* @return $url
*/
public function wpseo_canonical( $url ) {
return is_front_page( $url ) && get_option( 'permalink_structure' ) ? trailingslashit( $url ) : $url;
}
/**
* Fixes the links and strings stored in the indexable table since Yoast SEO 14.0
*
* @since 2.8.2
*
* @param object $presentation The indexable presentation.
* @return object
*/
public function frontend_presentation( $presentation ) {
switch ( $presentation->model->object_type ) {
case 'home-page':
$presentation->model->title = WPSEO_Options::get( 'title-home-wpseo' );
$presentation->model->description = WPSEO_Options::get( 'metadesc-home-wpseo' );
$presentation->model->open_graph_title = WPSEO_Options::get( 'og_frontpage_title' );
$presentation->model->open_graph_description = WPSEO_Options::get( 'og_frontpage_desc' );
break;
case 'post-type-archive':
if ( pll_is_translated_post_type( $presentation->model->object_sub_type ) ) {
$presentation->model->title = WPSEO_Options::get( 'title-ptarchive-' . $presentation->model->object_sub_type );
$presentation->model->description = WPSEO_Options::get( 'metadesc-ptarchive-' . $presentation->model->object_sub_type );
}
break;
case 'system-page':
switch ( $presentation->model->object_sub_type ) {
case '404':
$presentation->model->title = WPSEO_Options::get( 'title-404-wpseo' );
break;
case 'search-result':
$presentation->model->title = WPSEO_Options::get( 'title-search-wpseo' );
break;
}
break;
}
return $presentation;
}
/**
* Fixes the breadcrumb links and strings stored in the indexable table since Yoast SEO 14.0.
*
* In version 17.0, the breadcrumb links do not honor the filter `wpseo_dynamic_permalinks_enabled`.
*
* @since 2.8.3
*
* @param array $indexables An array of Indexable objects.
* @return array
*/
public function breadcrumb_indexables( $indexables ) {
foreach ( $indexables as &$indexable ) {
if ( 'home-page' === $indexable->object_type || ( 'post' === $indexable->object_type && 'page' === $indexable->object_sub_type && get_option( 'page_on_front' ) === $indexable->object_id ) ) {
// Handles both when the front page displays the list of posts or a static page.
$indexable->permalink = pll_home_url();
$indexable->breadcrumb_title = pll__( WPSEO_Options::get( 'breadcrumbs-home' ) );
} elseif ( 'post' === $indexable->object_type && 'page' === $indexable->object_sub_type && get_option( 'page_for_posts' ) === $indexable->object_id ) {
$indexable->permalink = get_permalink( $indexable->object_id );
} elseif ( 'post-type-archive' === $indexable->object_type && pll_is_translated_post_type( $indexable->object_sub_type ) ) {
$indexable->permalink = get_post_type_archive_link( $indexable->object_sub_type );
$breadcrumb_title = WPSEO_Options::get( 'bctitle-ptarchive-' . $indexable->object_sub_type );
$breadcrumb_title = $breadcrumb_title ?: $indexable->breadcrumb_title; // The option may be empty.
$indexable->breadcrumb_title = pll__( $breadcrumb_title );
} elseif ( 'term' === $indexable->object_type && pll_is_translated_taxonomy( $indexable->object_sub_type ) ) {
$indexable->permalink = get_term_link( $indexable->object_id );
}
}
return $indexables;
}
/**
* Copies or synchronizes the metas.
*
* @since 2.3.3
*
* @param string[] $keys List of custom fields names.
* @param bool $sync True if it is synchronization, false if it is a copy.
* @param int $from Id of the post from which we copy information.
* @param int $to Id of the post to which we paste information.
* @return array
*/
public function copy_post_metas( $keys, $sync, $from, $to ) {
if ( ! $sync ) {
// Text requiring translation.
$keys = array_merge( $keys, $this->get_translatable_meta_keys() );
// Copy the image urls.
$keys[] = '_yoast_wpseo_opengraph-image';
$keys[] = '_yoast_wpseo_twitter-image';
$keys[] = '_yoast_wpseo_meta-robots-noindex';
$keys[] = '_yoast_wpseo_meta-robots-nofollow';
$keys[] = '_yoast_wpseo_meta-robots-adv';
}
$taxonomies = get_taxonomies(
array(
'hierarchical' => true,
'public' => true,
)
);
$sync_taxonomies = PLL()->sync->taxonomies->get_taxonomies_to_copy( $sync, $from, $to );
$taxonomies = array_intersect( $taxonomies, $sync_taxonomies );
foreach ( $taxonomies as $taxonomy ) {
$keys[] = '_yoast_wpseo_primary_' . $taxonomy;
}
return $keys;
}
/**
* Translate the primary term during the synchronization process
*
* @since 2.3.3
*
* @param int $value Meta value.
* @param string $key Meta key.
* @param string $lang Language of target.
* @return int
*/
public function translate_post_meta( $value, $key, $lang ) {
if ( 0 !== strpos( $key, '_yoast_wpseo_primary_' ) ) {
return $value;
}
$taxonomy = str_replace( '_yoast_wpseo_primary_', '', $key );
if ( ! PLL()->model->is_translated_taxonomy( $taxonomy ) ) {
return $value;
}
return pll_get_term( $value, $lang );
}
/**
* Adds the yoast translatable metas to export.
*
* @param array $metas An array of post metas (keyed with meta keys) to export.
* @return array The modified array of post metas to export.
*/
public function export_post_metas( $metas ) {
$metas_to_export = array_fill_keys( $this->get_translatable_meta_keys(), 1 );
return array_merge( $metas, $metas_to_export );
}
/**
* Returns the meta keys with translatable text.
*
* @since 3.3
*
* @return string[]
*/
protected function get_translatable_meta_keys() {
return array(
'_yoast_wpseo_title',
'_yoast_wpseo_metadesc',
'_yoast_wpseo_bctitle',
'_yoast_wpseo_focuskw',
'_yoast_wpseo_opengraph-title',
'_yoast_wpseo_opengraph-description',
'_yoast_wpseo_twitter-title',
'_yoast_wpseo_twitter-description',
);
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* Loads the integration with Yet Another Related Posts Plugin.
*
* @package Polylang
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Don't access directly.
}
add_action(
'plugins_loaded',
function () {
if ( defined( 'YARPP_VERSION' ) ) {
add_action( 'init', array( PLL_Integrations::instance()->yarpp = new PLL_Yarpp(), 'init' ) );
}
},
0
);

View File

@@ -0,0 +1,20 @@
<?php
/**
* @package Polylang
*/
/**
* Manages the compatibility with Yet Another Related Posts Plugin.
*
* @since 2.8
*/
class PLL_Yarpp {
/**
* Just makes YARPP aware of the language taxonomy ( after Polylang registered it ).
*
* @since 1.0
*/
public function init() {
$GLOBALS['wp_taxonomies']['language']->yarpp_support = 1;
}
}