rebase from live enviornment
This commit is contained in:
76
wp/wp-content/mu-plugins/loader.php
Normal file
76
wp/wp-content/mu-plugins/loader.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Pantheon MU Plugin Loader
|
||||
* Description: Loads the MU plugins required to run the site
|
||||
* Author: Pantheon Systems
|
||||
* Author URI: https://pantheon.io
|
||||
* Version: 1.0
|
||||
*/
|
||||
|
||||
if ( defined( 'WP_INSTALLING' ) && WP_INSTALLING ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add mu-plugins here.
|
||||
$pantheon_mu_plugins = [
|
||||
'pantheon-mu-plugin/pantheon.php',
|
||||
];
|
||||
|
||||
foreach ( $pantheon_mu_plugins as $file ) {
|
||||
require_once WPMU_PLUGIN_DIR . '/' . $file;
|
||||
}
|
||||
unset( $file );
|
||||
|
||||
add_action( 'pre_current_active_plugins', function () use ( $pantheon_mu_plugins ) {
|
||||
global $plugins, $wp_list_table;
|
||||
|
||||
// Add our own mu-plugins to the page.
|
||||
foreach ( $pantheon_mu_plugins as $plugin_file ) {
|
||||
// Do not apply markup/translate as it'll be cached.
|
||||
$plugin_data = get_plugin_data( WPMU_PLUGIN_DIR . "/$plugin_file", false, false );
|
||||
|
||||
if ( empty( $plugin_data['Name'] ) ) {
|
||||
$plugin_data['Name'] = $plugin_file;
|
||||
}
|
||||
|
||||
$plugins['mustuse'][ $plugin_file ] = $plugin_data;
|
||||
}
|
||||
|
||||
// Recount totals.
|
||||
$GLOBALS['totals']['mustuse'] = count( $plugins['mustuse'] );
|
||||
|
||||
// Only apply the rest if we're actually looking at the page.
|
||||
if ( $GLOBALS['status'] !== 'mustuse' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset the list table's data.
|
||||
$wp_list_table->items = $plugins['mustuse'];
|
||||
foreach ( $wp_list_table->items as $plugin_file => $plugin_data ) {
|
||||
$wp_list_table->items[ $plugin_file ] = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, false, true );
|
||||
}
|
||||
|
||||
$total_this_page = $GLOBALS['totals']['mustuse'];
|
||||
|
||||
if ( $GLOBALS['orderby'] ) {
|
||||
uasort( $wp_list_table->items, [ $wp_list_table, '_order_callback' ] );
|
||||
}
|
||||
|
||||
// Force showing all plugins.
|
||||
// See https://core.trac.wordpress.org/ticket/27110.
|
||||
$plugins_per_page = $total_this_page;
|
||||
|
||||
$wp_list_table->set_pagination_args( [
|
||||
'total_items' => $total_this_page,
|
||||
'per_page' => $plugins_per_page,
|
||||
] );
|
||||
});
|
||||
|
||||
add_filter( 'network_admin_plugin_action_links', function ( $actions, $plugin_file, $plugin_data, $context ) use ( $pantheon_mu_plugins ) {
|
||||
if ( $context !== 'mustuse' || ! in_array( $plugin_file, $pantheon_mu_plugins, true ) ) {
|
||||
return $actions;
|
||||
}
|
||||
|
||||
$actions[] = sprintf( '<span style="color:#333">File: <code>%s</code></span>', $plugin_file );
|
||||
return $actions;
|
||||
}, 10, 4 );
|
||||
3
wp/wp-content/mu-plugins/pantheon-mu-plugin/.gitignore
vendored
Normal file
3
wp/wp-content/mu-plugins/pantheon-mu-plugin/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Ignore composer files.
|
||||
/vendor
|
||||
composer.lock
|
||||
1
wp/wp-content/mu-plugins/pantheon-mu-plugin/CODEOWNERS
Normal file
1
wp/wp-content/mu-plugins/pantheon-mu-plugin/CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
||||
* @pantheon-systems/cms-platform
|
||||
@@ -0,0 +1,16 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
indent_style = tab
|
||||
|
||||
[{.jshintrc,*.json,*.yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{*.txt,wp-config-sample.php}]
|
||||
end_of_line = crlf
|
||||
@@ -0,0 +1,63 @@
|
||||
#login {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
#return-to-pantheon {
|
||||
margin-bottom: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#return-to-pantheon .left {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
#return-to-pantheon a{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
color: #000000;
|
||||
padding: 5px 10px;
|
||||
background: #F8DD44;
|
||||
color: #000000 !important;
|
||||
text-decoration: none !important;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
min-width: 130px
|
||||
}
|
||||
|
||||
#return-to-pantheon a:hover {
|
||||
-webkit-transition: all 0.25s;
|
||||
-moz-transition: all 0.25s;
|
||||
transition: all 0.25s;
|
||||
background: #EFD01B;
|
||||
color: #333333 !important;
|
||||
}
|
||||
|
||||
#return-to-pantheon .fist-icon {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@media (max-width: 499px) {
|
||||
#login {
|
||||
width: 320px;
|
||||
}
|
||||
#return-to-pantheon {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#return-to-pantheon .left {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
#return-to-pantheon .right {
|
||||
margin-bottom: 25px;
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14px" height="32px" viewBox="0 0 14 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: Sketch 46.2 (44496) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>Group 11</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="WP---button" transform="translate(-322.000000, -538.000000)" fill="#333333">
|
||||
<g id="Group" transform="translate(311.000000, 534.000000)">
|
||||
<g id="Group-11" transform="translate(11.000000, 4.000000)">
|
||||
<path d="M1.54822908,0 L4.52272957,6.90999702 L0.736842105,6.90999702 L1.98837032,9.82347541 L9.66224514,9.82347541 L1.54822908,0 L1.54822908,0 Z M11.589856,24.7575559 L10.3368651,21.8425037 L8.57849426,21.8425037 L8.54163298,21.7553741 L6.11083637,16.1102593 L4.6957728,16.1102593 L7.16386951,21.8425037 L2.66269769,21.8425037 L10.7780302,31.6679821 L7.80265209,24.7575559 L11.589856,24.7575559 L11.589856,24.7575559 Z" id="Fill-1"></path>
|
||||
<path d="M6.3944081,15.35938 L5.16291955,12.493687 L4.54724842,12.493687 L5.77976089,15.3559463 L3.74741716,15.3559463 L6.2165378,21.0911952 L1.18058487,21.0911952 C0.756241333,21.0911952 0.522640287,21.0911952 0.330873868,20.4898718 C0.102099894,19.7718033 0,18.2748614 0,15.6365067 C0,12.9982951 0.102099894,11.5016393 0.330873868,10.7831416 C0.522640287,10.1818182 0.756241333,10.1818182 1.18058487,10.1818182 L6.73391219,10.1818182 L8.96270314,15.35938 L6.3944081,15.35938 Z M12.6233793,18.7798987 C12.7164101,18.7798987 12.9331895,18.892924 12.9331895,19.9363338 C12.9331895,20.9791714 12.7164101,21.0911952 12.6233793,21.0911952 L8.86294364,21.0911952 L7.86842046,18.7798987 L12.6233793,18.7798987 Z M12.6233793,12.493687 L8.3441065,12.493687 L7.34958333,10.1818182 L12.6233793,10.1818182 C12.7164101,10.1818182 12.9331895,10.2944143 12.9331895,11.3369657 C12.9331895,12.3800894 12.7164101,12.493687 12.6233793,12.493687 Z M13.063228,15.9142057 C13.1571364,15.9142057 13.3739159,16.0268018 13.3739159,17.0699255 C13.3739159,18.1130492 13.1571364,18.225073 13.063228,18.225073 L7.6291147,18.225073 L6.63415269,15.9142057 L13.063228,15.9142057 Z M13.063228,13.0485127 C13.1571364,13.0485127 13.3739159,13.1601073 13.3739159,14.2036602 C13.3739159,15.2463547 13.1571364,15.35938 13.063228,15.35938 L9.57837427,15.35938 L8.58297345,13.0485127 L13.063228,13.0485127 Z" id="Path"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,8 @@
|
||||
jQuery(document).ready(function( $ ) {
|
||||
|
||||
$('#return-to-pantheon')
|
||||
.detach()
|
||||
.prependTo('#loginform')
|
||||
.show();
|
||||
|
||||
});
|
||||
97
wp/wp-content/mu-plugins/pantheon-mu-plugin/inc/cli.php
Normal file
97
wp/wp-content/mu-plugins/pantheon-mu-plugin/inc/cli.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* WP-CLI commands for the Pantheon mu-plugin.
|
||||
*
|
||||
* @package pantheon
|
||||
*/
|
||||
|
||||
namespace Pantheon\CLI;
|
||||
|
||||
use Pantheon_Cache;
|
||||
use WP_CLI;
|
||||
|
||||
// Support the old pantheon-cache command but return a deprecation notice.
|
||||
WP_CLI::add_command( 'pantheon-cache set-maintenance-mode', '\\Pantheon\\CLI\\__deprecated_maintenance_mode_output' );
|
||||
WP_CLI::add_command( 'pantheon cache set-maintenance-mode', '\\Pantheon\\CLI\\set_maintenance_mode_command' );
|
||||
WP_CLI::add_command( 'pantheon set-maintenance-mode', '\\Pantheon\\CLI\\set_maintenance_mode_command' );
|
||||
|
||||
/**
|
||||
* Sets maintenance mode status.
|
||||
*
|
||||
* Enable maintenance mode to work on your site while serving cached pages
|
||||
* to visitors and bots, or everyone except administators.
|
||||
*
|
||||
* ## DEPRECATION NOTICE
|
||||
*
|
||||
* This command is deprecated and will be removed in a future release.
|
||||
* Use `pantheon set-maintenance-mode` instead.
|
||||
*
|
||||
* ## USAGE
|
||||
*
|
||||
* wp pantheon-cache set-maintenance-mode <status> (deprecated) or
|
||||
* wp pantheon cache set-maintenance-mode <status>
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <status>
|
||||
* : Maintenance mode status.
|
||||
* ---
|
||||
* options:
|
||||
* - disabled
|
||||
* - anonymous
|
||||
* - everyone
|
||||
* ---
|
||||
*
|
||||
* @subcommand set-maintenance-mode
|
||||
*
|
||||
* @deprecated 1.0.0
|
||||
*/
|
||||
function __deprecated_maintenance_mode_output( $args ) {
|
||||
$allowed_args = [ 'disabled', 'anonymous', 'everyone' ];
|
||||
$replacement_command = ( ! empty( $args && count( $args ) === 1 ) && in_array( $args[0], $allowed_args, true ) ) ? 'set-maintenance-mode ' . $args[0] : false;
|
||||
|
||||
// translators: %s is the replacement command.
|
||||
WP_CLI::warning( WP_CLI::colorize( '%y' . sprintf( __( 'This command is deprecated and will be removed in a future release. Use `wp pantheon %s` instead.', 'pantheon-systems' ), $replacement_command ) . '%n' ) );
|
||||
WP_CLI::line( __( 'Run `wp pantheon set-maintenance-mode --help` for more information.', 'pantheon-systems' ) );
|
||||
|
||||
// The command should fail before we get here, but in case it doesn't, display an error.
|
||||
if ( false === $replacement_command ) {
|
||||
WP_CLI::error( __( 'Invalid arguments. Run `wp pantheon set-maintenance-mode --help` for more infomation.', 'pantheon-systems' ) );
|
||||
}
|
||||
|
||||
set_maintenance_mode_command( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets maintenance mode status.
|
||||
*
|
||||
* Enable maintenance mode to work on your site while serving cached pages
|
||||
* to visitors and bots, or everyone except administators.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <status>
|
||||
* : Maintenance mode status.
|
||||
* ---
|
||||
* options:
|
||||
* - disabled
|
||||
* - anonymous
|
||||
* - everyone
|
||||
* ---
|
||||
*
|
||||
* @subcommand set-maintenance-mode
|
||||
*/
|
||||
function set_maintenance_mode_command( $args ) {
|
||||
|
||||
list( $status ) = $args;
|
||||
|
||||
$out = Pantheon_Cache()->default_options;
|
||||
if ( ! empty( $status )
|
||||
&& in_array( $status, [ 'anonymous', 'everyone' ], true ) ) {
|
||||
$out['maintenance_mode'] = $status;
|
||||
} else {
|
||||
$out['maintenance_mode'] = 'disabled';
|
||||
}
|
||||
update_option( Pantheon_Cache::SLUG, $out );
|
||||
WP_CLI::success( sprintf( 'Maintenance mode set to: %s', $out['maintenance_mode'] ) );
|
||||
}
|
||||
@@ -0,0 +1,704 @@
|
||||
<?php
|
||||
/**
|
||||
* File mostly copied from wp-admin/includes/network.php.
|
||||
*
|
||||
* Changes:
|
||||
* - Multisite instructions on step2
|
||||
* - Text area rows increased
|
||||
* - Allow altering config filename
|
||||
* - Allow altering config contents
|
||||
* - Remove if file_exists .htaccess
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for an existing network.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
*
|
||||
* @return string|false Base domain if network exists, otherwise false.
|
||||
*/
|
||||
function network_domain_check() {
|
||||
global $wpdb;
|
||||
|
||||
$sql = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $wpdb->site ) );
|
||||
if ( $wpdb->get_var( $sql ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
|
||||
return $wpdb->get_var( "SELECT domain FROM $wpdb->site ORDER BY id ASC LIMIT 1" );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow subdomain installation
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @return bool Whether subdomain installation is allowed
|
||||
*/
|
||||
function allow_subdomain_install() {
|
||||
$domain = preg_replace( '|https?://([^/]+)|', '$1', get_option( 'home' ) );
|
||||
if ( parse_url( get_option( 'home' ), PHP_URL_PATH ) || 'localhost' === $domain || preg_match( '|^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$|', $domain ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow subdirectory installation.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
*
|
||||
* @return bool Whether subdirectory installation is allowed
|
||||
*/
|
||||
function allow_subdirectory_install() {
|
||||
global $wpdb;
|
||||
|
||||
/**
|
||||
* Filters whether to enable the subdirectory installation feature in Multisite.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param bool $allow Whether to enable the subdirectory installation feature in Multisite.
|
||||
* Default false.
|
||||
*/
|
||||
if ( apply_filters( 'allow_subdirectory_install', false ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( defined( 'ALLOW_SUBDIRECTORY_INSTALL' ) && ALLOW_SUBDIRECTORY_INSTALL ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$post = $wpdb->get_row( "SELECT ID FROM $wpdb->posts WHERE post_date < DATE_SUB(NOW(), INTERVAL 1 MONTH) AND post_status = 'publish'" );
|
||||
if ( empty( $post ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get base domain of network.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @return string Base domain.
|
||||
*/
|
||||
function get_clean_basedomain() {
|
||||
$existing_domain = network_domain_check();
|
||||
if ( $existing_domain ) {
|
||||
return $existing_domain;
|
||||
}
|
||||
$domain = preg_replace( '|https?://|', '', get_option( 'siteurl' ) );
|
||||
$slash = strpos( $domain, '/' );
|
||||
if ( $slash ) {
|
||||
$domain = substr( $domain, 0, $slash );
|
||||
}
|
||||
return $domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints step 1 for Network installation process.
|
||||
*
|
||||
* @todo Realistically, step 1 should be a welcome screen explaining what a Network is and such.
|
||||
* Navigating to Tools > Network should not be a sudden "Welcome to a new install process!
|
||||
* Fill this out and click here." See also contextual help todo.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @global bool $is_apache
|
||||
*
|
||||
* @param false|WP_Error $errors Optional. Error object. Default false.
|
||||
*/
|
||||
function network_step1( $errors = false ) {
|
||||
if ( defined( 'DO_NOT_UPGRADE_GLOBAL_TABLES' ) ) {
|
||||
echo '<div class="error"><p><strong>' . esc_html__( 'Error:' ) . '</strong> ' . sprintf(
|
||||
/* translators: %s: DO_NOT_UPGRADE_GLOBAL_TABLES */
|
||||
esc_html__( 'The constant %s cannot be defined when creating a network.' ),
|
||||
'<code>DO_NOT_UPGRADE_GLOBAL_TABLES</code>'
|
||||
) . '</p></div>';
|
||||
echo '</div>';
|
||||
require_once ABSPATH . 'wp-admin/admin-footer.php';
|
||||
die();
|
||||
}
|
||||
|
||||
$active_plugins = get_option( 'active_plugins' );
|
||||
if ( ! empty( $active_plugins ) ) {
|
||||
echo '<div class="notice notice-warning"><p><strong>' . esc_html__( 'Warning:' ) . '</strong> ' . sprintf(
|
||||
/* translators: %s: URL to Plugins screen. */
|
||||
wp_kses_post( __( 'Please <a href="%s">deactivate your plugins</a> before enabling the Network feature.' ) ),
|
||||
esc_url_raw( admin_url( 'plugins.php?plugin_status=active' ) )
|
||||
) . '</p></div>';
|
||||
echo '<p>' . esc_html__( 'Once the network is created, you may reactivate your plugins.' ) . '</p>';
|
||||
echo '</div>';
|
||||
require_once ABSPATH . 'wp-admin/admin-footer.php';
|
||||
die();
|
||||
}
|
||||
|
||||
$hostname = get_clean_basedomain();
|
||||
$has_ports = strstr( $hostname, ':' );
|
||||
if ( ( false !== $has_ports && ! in_array( $has_ports, [ ':80', ':443' ], true ) ) ) {
|
||||
echo '<div class="error"><p><strong>' . esc_html__( 'Error:' ) . '</strong> ' . esc_html__( 'You cannot install a network of sites with your server address.' ) . '</p></div>';
|
||||
echo '<p>' . sprintf(
|
||||
/* translators: %s: Port number. */
|
||||
esc_html__( 'You cannot use port numbers such as %s.' ),
|
||||
'<code>' . $has_ports . '</code>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
) . '</p>';
|
||||
echo '<a href="' . esc_url( admin_url() ) . '">' . esc_html__( 'Go to Dashboard' ) . '</a>';
|
||||
echo '</div>';
|
||||
require_once ABSPATH . 'wp-admin/admin-footer.php';
|
||||
die();
|
||||
}
|
||||
|
||||
echo '<form method="post">';
|
||||
|
||||
wp_nonce_field( 'install-network-1' );
|
||||
|
||||
$error_codes = [];
|
||||
if ( is_wp_error( $errors ) ) {
|
||||
echo '<div class="error"><p><strong>' . esc_html__( 'Error: The network could not be created.' ) . '</strong></p>';
|
||||
foreach ( $errors->get_error_messages() as $error ) {
|
||||
echo "<p>$error</p>"; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
echo '</div>';
|
||||
$error_codes = $errors->get_error_codes();
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['sitename'] ) && ! in_array( 'empty_sitename', $error_codes, true ) ) {
|
||||
$site_name = $_POST['sitename'];
|
||||
} else {
|
||||
/* translators: %s: Default network title. */
|
||||
$site_name = sprintf( __( '%s Sites' ), get_option( 'blogname' ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['email'] ) && ! in_array( 'invalid_email', $error_codes, true ) ) {
|
||||
$admin_email = $_POST['email'];
|
||||
} else {
|
||||
$admin_email = get_option( 'admin_email' );
|
||||
}
|
||||
?>
|
||||
<p><?php esc_html_e( 'Welcome to the Network installation process!' ); ?></p>
|
||||
<p><?php esc_html_e( 'Fill in the information below and you’ll be on your way to creating a network of WordPress sites. Configuration files will be created in the next step.' ); ?></p>
|
||||
<?php
|
||||
|
||||
if ( isset( $_POST['subdomain_install'] ) ) {
|
||||
$subdomain_install = (bool) $_POST['subdomain_install'];
|
||||
} elseif ( apache_mod_loaded( 'mod_rewrite' ) ) { // Assume nothing.
|
||||
$subdomain_install = true;
|
||||
} elseif ( ! allow_subdirectory_install() ) {
|
||||
$subdomain_install = true;
|
||||
} else {
|
||||
$subdomain_install = false;
|
||||
}
|
||||
|
||||
if ( allow_subdomain_install() && allow_subdirectory_install() ) :
|
||||
?>
|
||||
<h3><?php esc_html_e( 'Addresses of Sites in your Network' ); ?></h3>
|
||||
<p><?php esc_html_e( 'Please choose whether you would like sites in your WordPress network to use sub-domains or sub-directories.' ); ?>
|
||||
<strong><?php esc_html_e( 'You cannot change this later.' ); ?></strong></p>
|
||||
<p><?php esc_html_e( 'You will need a wildcard DNS record if you are going to use the virtual host (sub-domain) functionality.' ); ?></p>
|
||||
<?php // @todo Link to an MS readme? ?>
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th><label><input type="radio" name="subdomain_install" value="1"<?php checked( $subdomain_install ); ?> /> <?php esc_html_e( 'Sub-domains' ); ?></label></th>
|
||||
<td>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: Host name. */
|
||||
wp_kses_post( _x( 'like <code>site1.%1$s</code> and <code>site2.%1$s</code>', 'subdomain examples' ) ),
|
||||
$hostname // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><label><input type="radio" name="subdomain_install" value="0"<?php checked( ! $subdomain_install ); ?> /> <?php esc_html_e( 'Sub-directories' ); ?></label></th>
|
||||
<td>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: Host name. */
|
||||
wp_kses_post( _x( 'like <code>%1$s/site1</code> and <code>%1$s/site2</code>', 'subdirectory examples' ) ),
|
||||
$hostname // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php
|
||||
endif;
|
||||
|
||||
if ( WP_CONTENT_DIR !== ABSPATH . 'wp-content' && ( allow_subdirectory_install() || ! allow_subdomain_install() ) ) {
|
||||
echo '<div class="error inline"><p><strong>' . esc_html__( 'Warning:' ) . '</strong> ' . esc_html__( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</p></div>';
|
||||
}
|
||||
|
||||
$is_www = ( 0 === strpos( $hostname, 'www.' ) );
|
||||
if ( $is_www ) :
|
||||
?>
|
||||
<h3><?php esc_html_e( 'Server Address' ); ?></h3>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: Site URL, 2: Host name, 3: www. */
|
||||
esc_html__( 'You should consider changing your site domain to %1$s before enabling the network feature. It will still be possible to visit your site using the %3$s prefix with an address like %2$s but any links will not have the %3$s prefix.' ),
|
||||
'<code>' . substr( $hostname, 4 ) . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'<code>' . $hostname . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'<code>www</code>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope='row'><?php esc_html_e( 'Server Address' ); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: Host name. */
|
||||
esc_html__( 'The internet address of your network will be %s.' ),
|
||||
'<code>' . $hostname . '</code>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3><?php esc_html_e( 'Network Details' ); ?></h3>
|
||||
<table class="form-table" role="presentation">
|
||||
<?php if ( 'localhost' === $hostname ) : ?>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Sub-directory Installation' ); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: localhost, 2: localhost.localdomain */
|
||||
esc_html__( 'Because you are using %1$s, the sites in your WordPress network must use sub-directories. Consider using %2$s if you wish to use sub-domains.' ),
|
||||
'<code>localhost</code>',
|
||||
'<code>localhost.localdomain</code>'
|
||||
);
|
||||
// Uh oh!
|
||||
if ( ! allow_subdirectory_install() ) {
|
||||
echo ' <strong>' . esc_html__( 'Warning:' ) . ' ' . esc_html__( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php elseif ( ! allow_subdomain_install() ) : ?>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Sub-directory Installation' ); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
esc_html_e( 'Because your installation is in a directory, the sites in your WordPress network must use sub-directories.' );
|
||||
// Uh oh!
|
||||
if ( ! allow_subdirectory_install() ) {
|
||||
echo ' <strong>' . esc_html__( 'Warning:' ) . ' ' . esc_html__( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php elseif ( ! allow_subdirectory_install() ) : ?>
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Sub-domain Installation' ); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
esc_html_e( 'Because your installation is not new, the sites in your WordPress network must use sub-domains.' );
|
||||
echo ' <strong>' . esc_html__( 'The main site in a sub-directory installation will need to use a modified permalink structure, potentially breaking existing links.' ) . '</strong>';
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php if ( ! $is_www ) : ?>
|
||||
<tr>
|
||||
<th scope='row'><?php esc_html_e( 'Server Address' ); ?></th>
|
||||
<td>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: Host name. */
|
||||
esc_html__( 'The internet address of your network will be %s.' ),
|
||||
'<code>' . $hostname . '</code>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<th scope='row'><label for="sitename"><?php esc_html_e( 'Network Title' ); ?></label></th>
|
||||
<td>
|
||||
<input name='sitename' id='sitename' type='text' size='45' value='<?php echo esc_attr( $site_name ); ?>' />
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'What would you like to call your network?' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope='row'><label for="email"><?php esc_html_e( 'Network Admin Email' ); ?></label></th>
|
||||
<td>
|
||||
<input name='email' id='email' type='text' size='45' value='<?php echo esc_attr( $admin_email ); ?>' />
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Your email address.' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button( __( 'Install' ), 'primary', 'submit' ); ?>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints step 2 for Network installation process.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
* @global bool $is_nginx Whether the server software is Nginx or something else.
|
||||
*
|
||||
* @param false|WP_Error $errors Optional. Error object. Default false.
|
||||
*/
|
||||
function network_step2( $errors = false ) {
|
||||
global $wpdb, $is_nginx;
|
||||
|
||||
$hostname = get_clean_basedomain();
|
||||
$slashed_home = trailingslashit( get_option( 'home' ) );
|
||||
$base = parse_url( $slashed_home, PHP_URL_PATH );
|
||||
$document_root_fix = str_replace( '\\', '/', realpath( $_SERVER['DOCUMENT_ROOT'] ) );
|
||||
$abspath_fix = str_replace( '\\', '/', ABSPATH );
|
||||
$home_path = 0 === strpos( $abspath_fix, $document_root_fix ) ? $document_root_fix . $base : get_home_path();
|
||||
$wp_siteurl_subdir = preg_replace( '#^' . preg_quote( $home_path, '#' ) . '#', '', $abspath_fix );
|
||||
$rewrite_base = ! empty( $wp_siteurl_subdir ) ? ltrim( trailingslashit( $wp_siteurl_subdir ), '/' ) : '';
|
||||
|
||||
$config_filename = 'wp-config.php';
|
||||
$config_filename = apply_filters( 'pantheon.multisite.config_filename', 'wp-config.php' );
|
||||
|
||||
$location_of_wp_config = $abspath_fix;
|
||||
if ( ! file_exists( ABSPATH . $config_filename ) && file_exists( dirname( ABSPATH ) . '/' . $config_filename ) ) {
|
||||
$location_of_wp_config = dirname( $abspath_fix );
|
||||
}
|
||||
$location_of_wp_config = trailingslashit( $location_of_wp_config );
|
||||
|
||||
// Wildcard DNS message.
|
||||
if ( is_wp_error( $errors ) ) {
|
||||
echo '<div class="error">' . esc_html( $errors->get_error_message() ) . '</div>';
|
||||
}
|
||||
|
||||
if ( $_POST ) {
|
||||
if ( allow_subdomain_install() ) {
|
||||
$subdomain_install = allow_subdirectory_install() ? ! empty( $_POST['subdomain_install'] ) : true;
|
||||
} else {
|
||||
$subdomain_install = false;
|
||||
}
|
||||
} elseif ( is_multisite() ) {
|
||||
$subdomain_install = is_subdomain_install();
|
||||
?>
|
||||
<p><?php esc_html_e( 'The original configuration steps are shown here for reference.' ); ?></p>
|
||||
<?php
|
||||
} else {
|
||||
$subdomain_install = (bool) $wpdb->get_var( "SELECT meta_value FROM $wpdb->sitemeta WHERE site_id = 1 AND meta_key = 'subdomain_install'" );
|
||||
?>
|
||||
<div class="error"><p><strong><?php esc_html_e( 'Warning:' ); ?></strong> <?php esc_html_e( 'An existing WordPress network was detected.' ); ?></p></div>
|
||||
<p><?php esc_html_e( 'Please complete the configuration steps. To create a new network, you will need to empty or remove the network database tables.' ); ?></p>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
$subdir_match = $subdomain_install ? '' : '([_0-9a-zA-Z-]+/)?';
|
||||
$subdir_replacement_01 = $subdomain_install ? '' : '$1';
|
||||
$subdir_replacement_12 = $subdomain_install ? '$1' : '$2';
|
||||
|
||||
if ( $_POST || ! is_multisite() ) {
|
||||
?>
|
||||
<h3><?php esc_html_e( 'Enabling the Network' ); ?></h3>
|
||||
<p><?php esc_html_e( 'Complete the following steps to enable the features for creating a network of sites.' ); ?></p>
|
||||
<div class="notice notice-warning inline"><p>
|
||||
<?php
|
||||
if ( file_exists( $home_path . 'web.config' ) ) {
|
||||
echo '<strong>' . esc_html__( 'Caution:' ) . '</strong> ';
|
||||
printf(
|
||||
/* translators: 1: wp-config.php, 2: web.config */
|
||||
esc_html__( 'You should back up your existing %1$s and %2$s files.' ),
|
||||
'<code>' . $config_filename . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'<code>web.config</code>'
|
||||
);
|
||||
} else {
|
||||
echo '<strong>' . esc_html__( 'Caution:' ) . '</strong> ';
|
||||
printf(
|
||||
/* translators: %s: wp-config.php */
|
||||
esc_html__( 'You should back up your existing %s file.' ),
|
||||
'<code>' . $config_filename . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
}
|
||||
?>
|
||||
</p></div>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<ol>
|
||||
<li><p id="network-wpconfig-rules-description">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: wp-config.php, 2: Location of wp-config file, 3: Translated version of "That's all, stop editing! Happy publishing." */
|
||||
esc_html__( 'Add the following to your %1$s file in %2$s <strong>above</strong> the line reading %3$s:' ),
|
||||
'<code>' . $config_filename . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
'<code>' . $location_of_wp_config . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
// translators: This string should only be translated if wp-config-sample.php is localized.
|
||||
// You can check the localized release package or https://i18n.svn.wordpress.org/<locale code>/branches/<wp version>/dist/wp-config-sample.php.
|
||||
'<code>/* ' . esc_html__( 'That’s all, stop editing! Happy publishing.' ) . ' */</code>'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<p class="configuration-rules-label"><label for="network-wpconfig-rules">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: File name (wp-config.php, .htaccess or web.config). */
|
||||
esc_html__( 'Network configuration rules for %s' ),
|
||||
'<code>' . $config_filename . '</code>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
?>
|
||||
</label></p>
|
||||
<textarea id="network-wpconfig-rules" class="code" readonly="readonly" cols="100" rows="31" aria-describedby="network-wpconfig-rules-description">
|
||||
<?php ob_start(); ?>
|
||||
if ( !empty( $_ENV['PANTHEON_ENVIRONMENT'] )) {
|
||||
$site_name = $_ENV['PANTHEON_SITE_NAME'];
|
||||
// Override $hostname value as needed.
|
||||
switch ( $_ENV['PANTHEON_ENVIRONMENT'] ) {
|
||||
case 'live':
|
||||
$hostname = $_SERVER['HTTP_HOST'];
|
||||
break;
|
||||
case 'test':
|
||||
$hostname = 'test-' . $site_name . '.pantheonsite.io';
|
||||
break;
|
||||
case 'dev':
|
||||
$hostname = 'dev-' . $site_name . '.pantheonsite.io';
|
||||
break;
|
||||
case 'lando':
|
||||
$hostname = $site_name . '.lndo.site';
|
||||
break;
|
||||
default:
|
||||
$hostname = $_ENV['PANTHEON_ENVIRONMENT'] . '-' . $site_name . '.pantheonsite.io';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Override with a default hostname.
|
||||
$hostname = '<?php echo $hostname; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>';
|
||||
}
|
||||
define( 'MULTISITE', true );
|
||||
define( 'SUBDOMAIN_INSTALL', <?php echo $subdomain_install ? 'true' : 'false'; ?> );
|
||||
define( 'DOMAIN_CURRENT_SITE', $hostname );
|
||||
define( 'PATH_CURRENT_SITE', '<?php echo $base; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>' );
|
||||
define( 'SITE_ID_CURRENT_SITE', 1 );
|
||||
define( 'BLOG_ID_CURRENT_SITE', 1 );
|
||||
<?php
|
||||
$config_file_contents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$config_file_contents = apply_filters( 'pantheon.multisite.config_contents', $config_file_contents );
|
||||
echo $config_file_contents; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
</textarea>
|
||||
<?php
|
||||
$keys_salts = [
|
||||
'AUTH_KEY' => '',
|
||||
'SECURE_AUTH_KEY' => '',
|
||||
'LOGGED_IN_KEY' => '',
|
||||
'NONCE_KEY' => '',
|
||||
'AUTH_SALT' => '',
|
||||
'SECURE_AUTH_SALT' => '',
|
||||
'LOGGED_IN_SALT' => '',
|
||||
'NONCE_SALT' => '',
|
||||
];
|
||||
foreach ( $keys_salts as $c => $v ) {
|
||||
if ( defined( $c ) ) {
|
||||
unset( $keys_salts[ $c ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $keys_salts ) ) {
|
||||
$keys_salts_str = '';
|
||||
$from_api = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
|
||||
if ( is_wp_error( $from_api ) ) {
|
||||
foreach ( $keys_salts as $c => $v ) {
|
||||
$keys_salts_str .= "\ndefine( '$c', '" . wp_generate_password( 64, true, true ) . "' );";
|
||||
}
|
||||
} else {
|
||||
$from_api = explode( "\n", wp_remote_retrieve_body( $from_api ) );
|
||||
foreach ( $keys_salts as $c => $v ) {
|
||||
$keys_salts_str .= "\ndefine( '$c', '" . substr( array_shift( $from_api ), 28, 64 ) . "' );";
|
||||
}
|
||||
}
|
||||
$num_keys_salts = count( $keys_salts );
|
||||
?>
|
||||
<p id="network-wpconfig-authentication-description">
|
||||
<?php
|
||||
if ( 1 === $num_keys_salts ) {
|
||||
printf(
|
||||
/* translators: %s: wp-config.php */
|
||||
esc_html__( 'This unique authentication key is also missing from your %s file.' ),
|
||||
'<code>' . $config_filename . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
} else {
|
||||
printf(
|
||||
/* translators: %s: wp-config.php */
|
||||
esc_html__( 'These unique authentication keys are also missing from your %s file.' ),
|
||||
'<code>' . $config_filename . '</code>', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
}
|
||||
?>
|
||||
<?php esc_html_e( 'To make your installation more secure, you should also add:' ); ?>
|
||||
</p>
|
||||
<p class="configuration-rules-label"><label for="network-wpconfig-authentication"><?php esc_html_e( 'Network configuration authentication keys' ); ?></label></p>
|
||||
<textarea id="network-wpconfig-authentication" class="code" readonly="readonly" cols="100" rows="<?php echo $num_keys_salts; ?>" aria-describedby="network-wpconfig-authentication-description"><?php echo esc_textarea( $keys_salts_str ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></textarea>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
<?php
|
||||
if ( iis7_supports_permalinks() ) :
|
||||
// IIS doesn't support RewriteBase, all your RewriteBase are belong to us.
|
||||
$iis_subdir_match = ltrim( $base, '/' ) . $subdir_match;
|
||||
$iis_rewrite_base = ltrim( $base, '/' ) . $rewrite_base;
|
||||
$iis_subdir_replacement = $subdomain_install ? '' : '{R:1}';
|
||||
|
||||
$web_config_file = '<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<system.webServer>
|
||||
<rewrite>
|
||||
<rules>
|
||||
<rule name="WordPress Rule 1" stopProcessing="true">
|
||||
<match url="^index\.php$" ignoreCase="false" />
|
||||
<action type="None" />
|
||||
</rule>';
|
||||
if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
|
||||
$web_config_file .= '
|
||||
<rule name="WordPress Rule for Files" stopProcessing="true">
|
||||
<match url="^' . $iis_subdir_match . 'files/(.+)" ignoreCase="false" />
|
||||
<action type="Rewrite" url="' . $iis_rewrite_base . WPINC . '/ms-files.php?file={R:1}" appendQueryString="false" />
|
||||
</rule>';
|
||||
}
|
||||
$web_config_file .= '
|
||||
<rule name="WordPress Rule 2" stopProcessing="true">
|
||||
<match url="^' . $iis_subdir_match . 'wp-admin$" ignoreCase="false" />
|
||||
<action type="Redirect" url="' . $iis_subdir_replacement . 'wp-admin/" redirectType="Permanent" />
|
||||
</rule>
|
||||
<rule name="WordPress Rule 3" stopProcessing="true">
|
||||
<match url="^" ignoreCase="false" />
|
||||
<conditions logicalGrouping="MatchAny">
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" />
|
||||
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" />
|
||||
</conditions>
|
||||
<action type="None" />
|
||||
</rule>
|
||||
<rule name="WordPress Rule 4" stopProcessing="true">
|
||||
<match url="^' . $iis_subdir_match . '(wp-(content|admin|includes).*)" ignoreCase="false" />
|
||||
<action type="Rewrite" url="' . $iis_rewrite_base . '{R:1}" />
|
||||
</rule>
|
||||
<rule name="WordPress Rule 5" stopProcessing="true">
|
||||
<match url="^' . $iis_subdir_match . '([_0-9a-zA-Z-]+/)?(.*\.php)$" ignoreCase="false" />
|
||||
<action type="Rewrite" url="' . $iis_rewrite_base . '{R:2}" />
|
||||
</rule>
|
||||
<rule name="WordPress Rule 6" stopProcessing="true">
|
||||
<match url="." ignoreCase="false" />
|
||||
<action type="Rewrite" url="index.php" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
';
|
||||
|
||||
echo '<li><p id="network-webconfig-rules-description">';
|
||||
printf(
|
||||
/* translators: 1: File name (.htaccess or web.config), 2: File path. */
|
||||
wp_kses_post( __( 'Add the following to your %1$s file in %2$s, <strong>replacing</strong> other WordPress rules:' ) ),
|
||||
'<code>web.config</code>',
|
||||
'<code>' . $home_path . '</code>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
echo '</p>';
|
||||
if ( ! $subdomain_install && WP_CONTENT_DIR !== ABSPATH . 'wp-content' ) {
|
||||
echo '<p><strong>' . esc_html__( 'Warning:' ) . ' ' . esc_html__( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</strong></p>';
|
||||
}
|
||||
?>
|
||||
<p class="configuration-rules-label"><label for="network-webconfig-rules">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: File name (wp-config.php, .htaccess or web.config). */
|
||||
esc_html__( 'Network configuration rules for %s' ),
|
||||
'<code>web.config</code>'
|
||||
);
|
||||
?>
|
||||
</label></p>
|
||||
<textarea id="network-webconfig-rules" class="code" readonly="readonly" cols="100" rows="20" aria-describedby="network-webconfig-rules-description"><?php echo esc_textarea( $web_config_file ); ?></textarea>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<?php
|
||||
elseif ( $is_nginx ) : // End iis7_supports_permalinks(). Link to Nginx documentation instead.
|
||||
|
||||
echo '<li><p>';
|
||||
printf(
|
||||
/* translators: %s: Documentation URL. */
|
||||
wp_kses_post( __( 'It seems your network is running with Nginx web server. <a href="%s">Learn more about further configuration</a>.' ) ),
|
||||
'https://wordpress.org/support/article/nginx/'
|
||||
);
|
||||
echo '</p></li>';
|
||||
|
||||
else : // End $is_nginx. Construct an .htaccess file instead.
|
||||
|
||||
$ms_files_rewriting = '';
|
||||
if ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) {
|
||||
$ms_files_rewriting = "\n# uploaded files\nRewriteRule ^";
|
||||
$ms_files_rewriting .= $subdir_match . "files/(.+) {$rewrite_base}" . WPINC . "/ms-files.php?file={$subdir_replacement_12} [L]" . "\n"; // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
|
||||
}
|
||||
|
||||
$htaccess_file = <<<EOF
|
||||
RewriteEngine On
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||||
RewriteBase {$base}
|
||||
RewriteRule ^index\.php$ - [L]
|
||||
{$ms_files_rewriting}
|
||||
# add a trailing slash to /wp-admin
|
||||
RewriteRule ^{$subdir_match}wp-admin$ {$subdir_replacement_01}wp-admin/ [R=301,L]
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} -d
|
||||
RewriteRule ^ - [L]
|
||||
RewriteRule ^{$subdir_match}(wp-(content|admin|includes).*) {$rewrite_base}{$subdir_replacement_12} [L]
|
||||
RewriteRule ^{$subdir_match}(.*\.php)$ {$rewrite_base}$subdir_replacement_12 [L]
|
||||
RewriteRule . index.php [L]
|
||||
|
||||
EOF;
|
||||
|
||||
echo '<li><p id="network-htaccess-rules-description">';
|
||||
printf(
|
||||
/* translators: 1: File name (.htaccess or web.config), 2: File path. */
|
||||
wp_kses_post( __( 'Add the following to your %1$s file in %2$s, <strong>replacing</strong> other WordPress rules:' ) ),
|
||||
'<code>.htaccess</code>',
|
||||
'<code>' . $home_path . '</code>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
);
|
||||
echo '</p>';
|
||||
if ( ! $subdomain_install && WP_CONTENT_DIR !== ABSPATH . 'wp-content' ) {
|
||||
echo '<p><strong>' . esc_html__( 'Warning:' ) . ' ' . esc_html__( 'Subdirectory networks may not be fully compatible with custom wp-content directories.' ) . '</strong></p>';
|
||||
}
|
||||
?>
|
||||
<p class="configuration-rules-label"><label for="network-htaccess-rules">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: File name (wp-config.php, .htaccess or web.config). */
|
||||
esc_html__( 'Network configuration rules for %s' ),
|
||||
'<code>.htaccess</code>'
|
||||
);
|
||||
?>
|
||||
</label></p>
|
||||
<textarea id="network-htaccess-rules" class="code" readonly="readonly" cols="100" rows="<?php echo substr_count( $htaccess_file, "\n" ) + 1; ?>" aria-describedby="network-htaccess-rules-description"><?php echo esc_textarea( $htaccess_file ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></textarea>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<?php
|
||||
endif; // End IIS/Nginx/Apache code branches.
|
||||
|
||||
if ( ! is_multisite() ) {
|
||||
?>
|
||||
<p><?php esc_html_e( 'Once you complete these steps, your network is enabled and configured. You will have to log in again.' ); ?> <a href="<?php echo esc_url( wp_login_url() ); ?>"><?php esc_html_e( 'Log In' ); ?></a></p>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/**
|
||||
* File mostly copied from wp-admin/network.php.
|
||||
*
|
||||
* Changes:
|
||||
* - s/__DIR__.'\//ABSPATH . 'wp-admin\//g
|
||||
* - s/ABSPATH . 'wp-admin\/includes\/network.php/__DIR__ . '\/includes-network.php/g'
|
||||
*/
|
||||
|
||||
define( 'WP_INSTALLING_NETWORK', true );
|
||||
|
||||
/** WordPress Administration Bootstrap */
|
||||
require_once ABSPATH . 'wp-admin/admin.php';
|
||||
|
||||
if ( ! current_user_can( 'setup_network' ) ) {
|
||||
wp_die( esc_html__( 'Sorry, you are not allowed to manage options for this site.' ) );
|
||||
}
|
||||
|
||||
if ( is_multisite() ) {
|
||||
if ( ! is_network_admin() ) {
|
||||
wp_safe_redirect( network_admin_url( 'setup.php' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! defined( 'MULTISITE' ) ) {
|
||||
wp_die( esc_html__( 'The Network creation panel is not for WordPress MU networks.' ) );
|
||||
}
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/includes-network.php';
|
||||
|
||||
// We need to create references to ms global tables to enable Network.
|
||||
foreach ( $wpdb->tables( 'ms_global' ) as $table => $prefixed_table ) {
|
||||
$wpdb->$table = $prefixed_table;
|
||||
}
|
||||
|
||||
if ( ! network_domain_check() && ( ! defined( 'WP_ALLOW_MULTISITE' ) || ! WP_ALLOW_MULTISITE ) ) {
|
||||
wp_die(
|
||||
printf( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
/* translators: 1: WP_ALLOW_MULTISITE, 2: wp-config.php */
|
||||
esc_html__( 'You must define the %1$s constant as true in your %2$s file to allow creation of a Network.' ),
|
||||
'<code>WP_ALLOW_MULTISITE</code>',
|
||||
'<code>wp-config.php</code>'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( is_network_admin() ) {
|
||||
// Used in the HTML title tag.
|
||||
$page_title = esc_html__( 'Network Setup' );
|
||||
} else {
|
||||
// Used in the HTML title tag.
|
||||
$page_title = __( 'Create a Network of WordPress Sites' );
|
||||
}
|
||||
|
||||
$network_help = wp_kses_post( '<p>' . __( 'This screen allows you to configure a network as having subdomains (<code>site1.example.com</code>) or subdirectories (<code>example.com/site1</code>). Subdomains require wildcard subdomains to be enabled in Apache and DNS records, if your host allows it.' ) . '</p>' .
|
||||
'<p>' . __( 'Choose subdomains or subdirectories; this can only be switched afterwards by reconfiguring your installation. Fill out the network details, and click Install. If this does not work, you may have to add a wildcard DNS record (for subdomains) or change to another setting in Permalinks (for subdirectories).' ) . '</p>' .
|
||||
'<p>' . __( 'The next screen for Network Setup will give you individually-generated lines of code to add to your wp-config.php and .htaccess files. Make sure the settings of your FTP client make files starting with a dot visible, so that you can find .htaccess; you may have to create this file if it really is not there. Make backup copies of those two files.' ) . '</p>' .
|
||||
'<p>' . __( 'Add the designated lines of code to wp-config.php (just before <code>/*...stop editing...*/</code>) and <code>.htaccess</code> (replacing the existing WordPress rules).' ) . '</p>' .
|
||||
'<p>' . __( 'Once you add this code and refresh your browser, multisite should be enabled. This screen, now in the Network Admin navigation menu, will keep an archive of the added code. You can toggle between Network Admin and Site Admin by clicking on the Network Admin or an individual site name under the My Sites dropdown in the Toolbar.' ) . '</p>' .
|
||||
'<p>' . __( 'The choice of subdirectory sites is disabled if this setup is more than a month old because of permalink problems with “/blog/” from the main site. This disabling will be addressed in a future version.' ) . '</p>' .
|
||||
'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
|
||||
'<p>' . __( '<a href="https://wordpress.org/support/article/create-a-network/">Documentation on Creating a Network</a>' ) . '</p>' .
|
||||
'<p>' . __( '<a href="https://wordpress.org/support/article/tools-network-screen/">Documentation on the Network Screen</a>' ) . '</p>' ); // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
|
||||
|
||||
get_current_screen()->add_help_tab(
|
||||
[
|
||||
'id' => 'network',
|
||||
'title' => __( 'Network' ),
|
||||
'content' => $network_help,
|
||||
]
|
||||
);
|
||||
|
||||
get_current_screen()->set_help_sidebar(
|
||||
'<p><strong>' . __( 'For more information:' ) . '</strong></p>' .
|
||||
'<p>' . __( '<a href="https://wordpress.org/support/article/create-a-network/">Documentation on Creating a Network</a>' ) . '</p>' .
|
||||
'<p>' . __( '<a href="https://wordpress.org/support/article/tools-network-screen/">Documentation on the Network Screen</a>' ) . '</p>' .
|
||||
'<p>' . __( '<a href="https://wordpress.org/support/">Support</a>' ) . '</p>'
|
||||
);
|
||||
|
||||
require_once ABSPATH . 'wp-admin/admin-header.php';
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php echo esc_html( $page_title ); ?></h1>
|
||||
|
||||
<?php
|
||||
if ( $_POST ) {
|
||||
|
||||
check_admin_referer( 'install-network-1' );
|
||||
|
||||
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
|
||||
// Create network tables.
|
||||
install_network();
|
||||
$base = parse_url( trailingslashit( get_option( 'home' ) ), PHP_URL_PATH );
|
||||
$subdomain_install = allow_subdomain_install() ? ! empty( $_POST['subdomain_install'] ) : false;
|
||||
if ( ! network_domain_check() ) {
|
||||
$result = populate_network( 1, get_clean_basedomain(), sanitize_email( $_POST['email'] ), wp_unslash( $_POST['sitename'] ), $base, $subdomain_install );
|
||||
if ( is_wp_error( $result ) ) {
|
||||
if ( 1 === count( $result->get_error_codes() ) && 'no_wildcard_dns' === $result->get_error_code() ) {
|
||||
network_step2( $result );
|
||||
} else {
|
||||
network_step1( $result );
|
||||
}
|
||||
} else {
|
||||
network_step2();
|
||||
}
|
||||
} else {
|
||||
network_step2();
|
||||
}
|
||||
} elseif ( is_multisite() || network_domain_check() ) {
|
||||
network_step2();
|
||||
} else {
|
||||
network_step1();
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php require_once ABSPATH . 'wp-admin/admin-footer.php'; ?>
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Modify the WordPress login form for Pantheon
|
||||
*/
|
||||
|
||||
/**
|
||||
* Should we proceed with adding the return to Pantheon button?
|
||||
*
|
||||
* Only if we are on a Pantheon subdomain
|
||||
*/
|
||||
$show_return_to_pantheon_button = apply_filters( 'show_return_to_pantheon_button', (
|
||||
(
|
||||
false !== stripos( get_site_url(), 'pantheonsite.io' ) ||
|
||||
( isset( $_SERVER['HTTP_HOST'] ) && false !== stripos( $_SERVER['HTTP_HOST'], 'pantheonsite.io' ) )
|
||||
)
|
||||
) );
|
||||
|
||||
if ( $show_return_to_pantheon_button ) {
|
||||
|
||||
/**
|
||||
* Enqueue Pantheon login styles
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function Pantheon_Enqueue_Login_style() {
|
||||
wp_enqueue_style( 'pantheon-login-mods', plugin_dir_url( __FILE__ ) . 'assets/css/return-to-pantheon-button.css', false, PANTHEON_MU_PLUGIN_VERSION );
|
||||
}
|
||||
|
||||
add_action( 'login_enqueue_scripts', 'Pantheon_Enqueue_Login_style', 10 );
|
||||
|
||||
/**
|
||||
* Enqueue Pantheon login scripts
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function Pantheon_Enqueue_Login_script() {
|
||||
wp_enqueue_script( 'pantheon-login-mods', plugin_dir_url( __FILE__ ) . 'assets/js/return-to-pantheon-button.js', [ 'jquery' ], PANTHEON_MU_PLUGIN_VERSION, true );
|
||||
}
|
||||
|
||||
add_action( 'login_enqueue_scripts', 'Pantheon_Enqueue_Login_script', 1 );
|
||||
|
||||
/**
|
||||
* Print return to Pantheon link HTML
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function Return_To_Pantheon_Button_HTML() {
|
||||
$pantheon_dashboard_url = 'https://dashboard.pantheon.io/sites/' . $_ENV['PANTHEON_SITE'] . '#' . $_ENV['PANTHEON_ENVIRONMENT'];
|
||||
|
||||
$pantheon_fist_icon_url = plugin_dir_url( __FILE__ ) . 'assets/images/pantheon-fist-icon-black.svg';
|
||||
$login_message = apply_filters( 'pantheon_wp_login_text', esc_html__( 'Login to your WordPress Site', 'pantheon' ) );
|
||||
?>
|
||||
<div id="return-to-pantheon" style="display: none;">
|
||||
<div class="left">
|
||||
<?php echo $login_message; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a href="<?php echo esc_url( $pantheon_dashboard_url ); ?>">
|
||||
<img class="fist-icon" src="<?php echo esc_url( $pantheon_fist_icon_url ); ?>">
|
||||
<?php esc_html_e( 'Return to Pantheon', 'pantheon' ); ?>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action( 'login_header', 'Return_To_Pantheon_Button_HTML', 10 );
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* If a site has multisite enabled, but has not had the final installation
|
||||
* steps completed, alert the user and provide links.
|
||||
*
|
||||
* @package pantheon
|
||||
*/
|
||||
|
||||
/**
|
||||
* Detects if a user is using the correct upstream and framework and give them appropriate next steps to finalize WPMS setup.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function pantheon_multisite_install_finalize_message() {
|
||||
?>
|
||||
<div class="notice notice-info is-dismissible">
|
||||
<?php
|
||||
if ( isset( $_ENV['PANTHEON_ENVIRONMENT'] ) ) {
|
||||
if ( getenv( 'FRAMEWORK' ) === 'wordpress_network' ) {
|
||||
?>
|
||||
<p><?php esc_html_e( 'Your WordPress Multisite is almost ready!', 'pantheon' ); ?></p>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
wp_kses_post(
|
||||
// translators: %s is the link to the Pantheon Multisite Configuration documentation.
|
||||
__( 'Visit <a href="%s">Pantheon Multisite Configuration</a> for documentation on how to finalize configuration of your site network.', 'pantheon' )
|
||||
),
|
||||
'https://pantheon.io/docs/guides/multisite/config/#install-the-wordpress-site-network'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php
|
||||
} else {
|
||||
?>
|
||||
<p><?php esc_html_e( 'You are trying to configure a WordPress Multisite with a wrong upstream!', 'pantheon' ); ?></p>
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
wp_kses_post(
|
||||
// translators: %s is the link to the Pantheon Support page.
|
||||
__( 'Make sure that you have the correct upstream configuration for WPMS. If you do not have that capability or to check if you are eligible, please <a href="%s">Contact Support</a>.', 'pantheon' )
|
||||
), 'https://pantheon.io/support'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action( 'admin_notices', 'pantheon_multisite_install_finalize_message' );
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Network Setup
|
||||
*
|
||||
* @package pantheon-mu-plugin
|
||||
*/
|
||||
|
||||
namespace Pantheon\NetworkSetup;
|
||||
|
||||
/**
|
||||
* Alter network setup pages to include Pantheon-specific instructions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Replace the WordPress core Network Setup page from the Settings menu.
|
||||
*/
|
||||
function pantheon_remove_network_setup() {
|
||||
global $submenu;
|
||||
if ( isset( $submenu['tools.php'][50] ) ) {
|
||||
unset( $submenu['tools.php'][50] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the Pantheon network setup submenu page.
|
||||
*/
|
||||
function pantheon_add_network_setup() {
|
||||
add_management_page(
|
||||
__( 'Create a Network of WordPress Sites', 'network-setup' ),
|
||||
__( 'Network Setup', 'network-setup' ),
|
||||
'setup_network',
|
||||
'setup_network',
|
||||
__NAMESPACE__ . '\\pantheon_render_network_setup_page'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Pantheon network setup page.
|
||||
*/
|
||||
function pantheon_render_network_setup_page() {
|
||||
global $wpdb;
|
||||
require_once __DIR__ . '/network/network.php';
|
||||
}
|
||||
|
||||
add_action( 'admin_menu', __NAMESPACE__ . '\\pantheon_remove_network_setup' );
|
||||
add_action( 'admin_menu', __NAMESPACE__ . '\\pantheon_add_network_setup' );
|
||||
@@ -0,0 +1,547 @@
|
||||
<?php
|
||||
/**
|
||||
* Pantheon Page Cache
|
||||
*
|
||||
* @package pantheon-mu-plugin
|
||||
*/
|
||||
|
||||
/**
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
class Pantheon_Cache {
|
||||
|
||||
/**
|
||||
* Define the capability required to see and modify the settings page.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $options_capability = 'manage_options';
|
||||
|
||||
/**
|
||||
* Define the default options, which are overridden by what's in wp_options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $default_options = [];
|
||||
|
||||
/**
|
||||
* Stores the options for this plugin (from wp_options).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options = [];
|
||||
|
||||
/**
|
||||
* Store the Paths to be flushed at shutdown.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $paths = [];
|
||||
|
||||
/**
|
||||
* The slug for the plugin, used in various places like the options page.
|
||||
*/
|
||||
const SLUG = 'pantheon-cache';
|
||||
|
||||
/**
|
||||
* Holds the singleton instance.
|
||||
*
|
||||
* @static
|
||||
* @var object
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Get a reference to the singleton.
|
||||
*
|
||||
* @return object The singleton instance.
|
||||
*/
|
||||
public static function instance() {
|
||||
if ( ! isset( self::$instance ) ) {
|
||||
self::$instance = new Pantheon_Cache();
|
||||
self::$instance->setup();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
protected function __construct() {
|
||||
/** Don't do anything */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Setup the actions and filters we need to hook into, and initialize any properties we need.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function setup() {
|
||||
$this->options = get_option( self::SLUG, [] );
|
||||
$this->default_options = [
|
||||
'default_ttl' => 600,
|
||||
'maintenance_mode' => 'disabled',
|
||||
];
|
||||
$this->options = wp_parse_args( $this->options, $this->default_options );
|
||||
|
||||
add_action( 'init', [ $this, 'action_init_do_maintenance_mode' ] );
|
||||
|
||||
add_action( 'admin_init', [ $this, 'action_admin_init' ] );
|
||||
add_action( 'admin_menu', [ $this, 'action_admin_menu' ] );
|
||||
add_action( 'load-plugin-install.php', [ $this, 'action_load_plugin_install' ] );
|
||||
|
||||
add_action( 'admin_post_pantheon_cache_flush_site', [ $this, 'flush_site' ] );
|
||||
|
||||
add_action( 'send_headers', [ $this, 'cache_add_headers' ] );
|
||||
add_filter( 'rest_post_dispatch', [ $this, 'filter_rest_post_dispatch_send_cache_control' ], 10, 2 );
|
||||
|
||||
add_action( 'admin_notices', function () {
|
||||
global $wp_object_cache;
|
||||
if ( empty( $wp_object_cache->missing_redis_message ) ) {
|
||||
return;
|
||||
}
|
||||
$wp_object_cache->missing_redis_message = 'Alert! The Pantheon Redis service needs to be enabled before the WP Redis object cache will function properly.';
|
||||
}, 9 ); // Before the message is displayed in the plugin notice.
|
||||
|
||||
add_action( 'shutdown', [ $this, 'cache_clean_urls' ], 999 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays maintenance mode when enabled.
|
||||
*/
|
||||
public function action_init_do_maintenance_mode() {
|
||||
|
||||
$do_maintenance_mode = false;
|
||||
|
||||
if ( in_array( $this->options['maintenance_mode'], [ 'anonymous', 'everyone' ], true )
|
||||
&& ! is_user_logged_in() ) {
|
||||
$do_maintenance_mode = true;
|
||||
}
|
||||
|
||||
if ( 'everyone' === $this->options['maintenance_mode']
|
||||
&& is_user_logged_in()
|
||||
&& ! current_user_can( 'manage_options' ) ) {
|
||||
$do_maintenance_mode = true;
|
||||
}
|
||||
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
$do_maintenance_mode = false;
|
||||
}
|
||||
|
||||
if ( 'wp-login.php' === $GLOBALS['pagenow'] ) {
|
||||
$do_maintenance_mode = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify maintenance mode behavior with more advanced conditionals.
|
||||
*
|
||||
* @var boolean $do_maintenance_mode Whether or not to do maintenance mode.
|
||||
*/
|
||||
$do_maintenance_mode = apply_filters( 'pantheon_cache_do_maintenance_mode', $do_maintenance_mode );
|
||||
|
||||
if ( ! $do_maintenance_mode ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_die(
|
||||
esc_html__( 'Briefly unavailable for scheduled maintenance. Check back in a minute.' ),
|
||||
esc_html__( 'Maintenance' ),
|
||||
503
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prep the Settings API.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function action_admin_init() {
|
||||
register_setting( self::SLUG, self::SLUG, [ self::$instance, 'sanitize_options' ] );
|
||||
add_settings_section( 'general', false, '__return_false', self::SLUG );
|
||||
add_settings_field( 'default_ttl', null, [ self::$instance, 'default_ttl_field' ], self::SLUG, 'general' );
|
||||
add_settings_field( 'maintenance_mode', null, [ self::$instance, 'maintenance_mode_field' ], self::SLUG, 'general' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the settings page to the menu.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function action_admin_menu() {
|
||||
add_options_page( __( 'Pantheon Page Cache', 'pantheon-cache' ), __( 'Pantheon Page Cache', 'pantheon-cache' ), $this->options_capability, self::SLUG, [ self::$instance, 'view_settings_page' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if JavaScript should trigger the opening of the plugin install box
|
||||
*/
|
||||
public function action_load_plugin_install() {
|
||||
if ( empty( $_GET['action'] ) || 'pantheon-load-infobox' !== $_GET['action'] ) {
|
||||
return;
|
||||
}
|
||||
add_action( 'admin_footer', [ $this, 'action_admin_footer_trigger_plugin_open' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the opening of the Pantheon Advanced Page Cache infobox
|
||||
*/
|
||||
public function action_admin_footer_trigger_plugin_open() {
|
||||
?>
|
||||
<script>
|
||||
jQuery(document).ready(function(){
|
||||
// Wait until the click event handler is bound by core JavaScript
|
||||
setTimeout(function(){
|
||||
jQuery('.plugin-card-pantheon-advanced-page-cache a.open-plugin-details-modal').trigger('click');
|
||||
}, 1 )
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the HTML for the default TTL field.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function default_ttl_field() {
|
||||
echo '<h3>' . esc_html__( 'Default Time to Live (TTL)', 'pantheon-cache' ) . '</h3>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<p>' . esc_html__( 'Maximum time a cached page will be served. A higher TTL typically improves site performance.', 'pantheon-cache' ) . '</p>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<input type="text" name="' . self::SLUG . '[default_ttl]" value="' . $this->options['default_ttl'] . '" size="5" /> ' . esc_html__( 'seconds', 'pantheon-cache' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the HTML for the maintenance mode field.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maintenance_mode_field() {
|
||||
echo '<h3>' . esc_html__( 'Maintenance Mode', 'pantheon-cache' ) . '</h3>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<p>' . esc_html__( 'Enable maintenance mode to work on your site while serving cached pages to:', 'pantheon-cache' ) . '</p>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<label style="display: block; margin-bottom: 5px;"><input type="radio" name="' . self::SLUG . '[maintenance_mode]" value="" ' . checked( 'disabled', $this->options['maintenance_mode'], false ) . ' /> ' . esc_html__( 'Disabled', 'pantheon-cache' ) . '</label>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<label style="display: block; margin-bottom: 5px;"><input type="radio" name="' . self::SLUG . '[maintenance_mode]" value="anonymous" ' . checked( 'anonymous', $this->options['maintenance_mode'], false ) . ' /> ' . esc_html__( 'Logged-Out Visitors', 'pantheon-cache' ) . '</label>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo '<label style="display: block; margin-bottom: 5px;"><input type="radio" name="' . self::SLUG . '[maintenance_mode]" value="everyone" ' . checked( 'everyone', $this->options['maintenance_mode'], false ) . ' /> ' . esc_html__( 'Everyone except Administrators', 'pantheon-cache' ) . '</label>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitize our options.
|
||||
*
|
||||
* @param array $in The POST values.
|
||||
* @return array The sanitized POST values.
|
||||
*/
|
||||
public function sanitize_options( $in ) {
|
||||
$out = $this->default_options;
|
||||
|
||||
// Validate default_ttl.
|
||||
$out['default_ttl'] = absint( $in['default_ttl'] );
|
||||
if ( $out['default_ttl'] < 60 && isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && 'live' === $_ENV['PANTHEON_ENVIRONMENT'] ) {
|
||||
$out['default_ttl'] = 60;
|
||||
}
|
||||
|
||||
if ( ! empty( $in['maintenance_mode'] )
|
||||
&& in_array( $in['maintenance_mode'], [ 'anonymous', 'everyone' ], true ) ) {
|
||||
$out['maintenance_mode'] = $in['maintenance_mode'];
|
||||
} else {
|
||||
$out['maintenance_mode'] = 'disabled';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Output the settings page.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function view_settings_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2><?php esc_html_e( 'Pantheon Page Cache', 'pantheon-cache' ); ?></h2>
|
||||
|
||||
<?php if ( ! empty( $_GET['cache-cleared'] ) && 'true' === $_GET['cache-cleared'] ) : ?>
|
||||
<div class="updated below-h2">
|
||||
<p><?php esc_html_e( 'Site cache flushed.', 'pantheon-cache' ); ?></p>
|
||||
</div>
|
||||
<?php endif ?>
|
||||
|
||||
<?php if ( class_exists( 'Pantheon_Advanced_Page_Cache\Purger' ) ) : // translators: %s is a link. ?>
|
||||
<div class="notice notice-success"><p><?php echo wp_kses_post( sprintf( __( 'Pantheon Advanced Page Cache activated. <a target="_blank" href="%s">Learn more</a>', 'pantheon-cache' ), 'https://docs.pantheon.io/guides/wordpress-configurations/wordpress-cache-plugin' ) ); ?></p></div>
|
||||
<?php else : // translators: %s is a link. ?>
|
||||
<div class="notice notice-warning"><p><?php echo wp_kses_post( sprintf( __( 'Want to automatically clear related pages when you update content? Learn more about the <a href="%s">Pantheon Advanced Page Cache</a>.', 'pantheon-cache' ), 'https://docs.pantheon.io/guides/wordpress-configurations/wordpress-cache-plugin' ) ); ?></p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Permits the Pantheon Advanced Page Cache plugin to add
|
||||
* supplemental text.
|
||||
*/
|
||||
do_action( 'pantheon_cache_settings_page_top' );
|
||||
?>
|
||||
|
||||
<?php if ( apply_filters( 'pantheon_cache_allow_clear_all', true ) ) : ?>
|
||||
|
||||
<form action="admin-post.php" method="POST">
|
||||
<input type="hidden" name="action" value="pantheon_cache_flush_site" />
|
||||
<?php wp_nonce_field( 'pantheon-cache-clear-all', 'pantheon-cache-nonce' ); ?>
|
||||
<h3><?php esc_html_e( 'Clear Site Cache', 'pantheon-cache' ); ?></h3>
|
||||
<p><?php esc_html_e( 'Use with care. Clearing the entire site cache will negatively impact performance for a short period of time.', 'pantheon-cache' ); ?></p>
|
||||
<?php submit_button( __( 'Clear Cache', 'pantheon-cache' ), 'secondary' ); ?>
|
||||
</form>
|
||||
|
||||
<hr />
|
||||
|
||||
<?php endif ?>
|
||||
|
||||
<style>
|
||||
.ttl-form th[scope="row"] {
|
||||
display: none;
|
||||
}
|
||||
.ttl-form td {
|
||||
padding-left: 0;
|
||||
}
|
||||
.ttl-form td p {
|
||||
margin-bottom: 1em;
|
||||
font-size: 13px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<form action="options.php" method="POST" class="ttl-form">
|
||||
<?php settings_fields( self::SLUG ); ?>
|
||||
<?php do_settings_sections( self::SLUG ); ?>
|
||||
<?php submit_button( __( 'Save Changes', 'pantheon-cache' ) ); ?>
|
||||
</form>
|
||||
|
||||
<hr />
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Permits the Pantheon Advanced Page Cache plugin to add
|
||||
* supplemental text.
|
||||
*/
|
||||
do_action( 'pantheon_cache_settings_page_bottom' );
|
||||
?>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache-control header value.
|
||||
*
|
||||
* This removes "max-age=0" which could hypothetically be used by
|
||||
* Varnish on an immediate subsequent request.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function get_cache_control_header_value() {
|
||||
if ( ! is_admin() && ! is_user_logged_in() ) {
|
||||
$ttl = absint( $this->options['default_ttl'] );
|
||||
if ( $ttl < 60 && isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && 'live' === $_ENV['PANTHEON_ENVIRONMENT'] ) {
|
||||
$ttl = 60;
|
||||
}
|
||||
|
||||
return sprintf( 'public, max-age=%d', $ttl );
|
||||
} else {
|
||||
return 'no-cache, no-store, must-revalidate';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the cache-control header.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function cache_add_headers() {
|
||||
header( sprintf( 'cache-control: %s', $this->get_cache_control_header_value() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the cache control header for REST API requests
|
||||
*
|
||||
* @param WP_REST_Response $response Response.
|
||||
* @return WP_REST_Response Response.
|
||||
*/
|
||||
public function filter_rest_post_dispatch_send_cache_control( $response ) {
|
||||
$response->header( 'Cache-Control', $this->get_cache_control_header_value() );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache for the entire site.
|
||||
*
|
||||
* @return void|false
|
||||
*/
|
||||
public function flush_site() {
|
||||
if ( ! function_exists( 'current_user_can' ) || false === current_user_can( 'manage_options' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['pantheon-cache-nonce'] ) && wp_verify_nonce( $_POST['pantheon-cache-nonce'], 'pantheon-cache-clear-all' ) ) {
|
||||
if ( function_exists( 'pantheon_clear_edge_all' ) ) {
|
||||
pantheon_clear_edge_all();
|
||||
}
|
||||
wp_cache_flush();
|
||||
wp_safe_redirect( admin_url( 'options-general.php?page=pantheon-cache&cache-cleared=true' ) );
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the cache for a post.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param int $post_id A post ID to clean.
|
||||
* @return void
|
||||
*/
|
||||
public function clean_post_cache( $post_id, $include_homepage = true ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable,Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
|
||||
if ( method_exists( 'Pantheon_Advanced_Page_Cache\Purger', 'action_clean_post_cache' ) ) {
|
||||
Pantheon_Advanced_Page_Cache\Purger::action_clean_post_cache( $post_id );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the cache for a given term or terms and taxonomy.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param int|array $term_ids Single or list of Term IDs.
|
||||
* @param string $taxonomy Can be empty and will assume tt_ids, else will use for context.
|
||||
* @return void
|
||||
*/
|
||||
public function clean_term_cache( $term_ids, $taxonomy ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed,VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
if ( method_exists( 'Pantheon_Advanced_Page_Cache\Purger', 'action_clean_term_cache' ) ) {
|
||||
Pantheon_Advanced_Page_Cache\Purger::action_clean_term_cache( $term_ids );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the cache for a given term or terms and taxonomy.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param int|array $object_ids Single or list of term object ID(s).
|
||||
* @param array|string $object_type The taxonomy object type.
|
||||
* @return void
|
||||
*/
|
||||
public function clean_object_term_cache( $object_ids, $object_type ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
// Handled by Pantheon Integrated CDN.
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Fully-qualified urls to be cleared on shutdown.
|
||||
*
|
||||
* @param array|string $urls List of full urls to clear.
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_urls( $urls ) {
|
||||
$paths = [];
|
||||
$urls = array_filter( (array) $urls, 'is_string' );
|
||||
foreach ( $urls as $full_url ) {
|
||||
// Parse down to the path+query, escape regex.
|
||||
$parsed = parse_url( $full_url );
|
||||
// Sometimes parse_url can return false, on malformed urls.
|
||||
if ( false === $parsed ) {
|
||||
continue;
|
||||
}
|
||||
// Build up the path, checking if the array key exists first.
|
||||
if ( array_key_exists( 'path', $parsed ) ) {
|
||||
$path = $parsed['path'];
|
||||
if ( array_key_exists( 'query', $parsed ) ) {
|
||||
$path = $path . $parsed['query'];
|
||||
}
|
||||
} else {
|
||||
// If the path doesn't exist, set it to the null string.
|
||||
$path = '';
|
||||
}
|
||||
if ( '' === $path ) {
|
||||
continue;
|
||||
}
|
||||
$path = '^' . preg_quote( $path ) . '$'; // phpcs:ignore WordPress.PHP.PregQuoteDelimiter.Missing
|
||||
$paths[] = $path;
|
||||
}
|
||||
|
||||
$this->paths = array_merge( $this->paths, $paths );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue a regex to be cleared.
|
||||
*
|
||||
* You must understand regular expressions to use this, and be careful.
|
||||
*
|
||||
* @param string $regex path regex to clear.
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue_regex( $regex ) {
|
||||
$this->paths[] = $regex;
|
||||
}
|
||||
|
||||
|
||||
public function cache_clean_urls() {
|
||||
if ( empty( $this->paths ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->paths = apply_filters( 'pantheon_clean_urls', array_unique( $this->paths ) );
|
||||
|
||||
// Call the big daddy here.
|
||||
$this->paths = apply_filters( 'pantheon_final_clean_urls', $this->paths );
|
||||
if ( function_exists( 'pantheon_clear_edge_paths' ) ) {
|
||||
pantheon_clear_edge_paths( $this->paths );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a reference to the singleton.
|
||||
*
|
||||
* This can be used to reference public methods, e.g. `Pantheon_Cache()->clean_post_cache( 123 )`
|
||||
*/
|
||||
function Pantheon_Cache() {
|
||||
return Pantheon_Cache::instance();
|
||||
}
|
||||
add_action( 'plugins_loaded', 'Pantheon_Cache' );
|
||||
|
||||
/**
|
||||
* @see Pantheon_Cache::clean_post_cache
|
||||
*
|
||||
* @deprecated Please call Pantheon Integrated CDN instead.
|
||||
*/
|
||||
function pantheon_clean_post_cache( $post_id, $include_homepage = true ) {
|
||||
Pantheon_Cache()->clean_post_cache( $post_id, $include_homepage );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see Pantheon_Cache::clean_term_cache
|
||||
*
|
||||
* @deprecated Please call Pantheon Integrated CDN instead.
|
||||
*/
|
||||
function pantheon_clean_term_cache( $term_ids, $taxonomy ) {
|
||||
Pantheon_Cache()->clean_term_cache( $term_ids, $taxonomy );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see Pantheon_Cache::enqueue_urls
|
||||
*
|
||||
* @deprecated Please call Pantheon Integrated CDN instead.
|
||||
*/
|
||||
function pantheon_enqueue_urls( $urls ) {
|
||||
Pantheon_Cache()->enqueue_urls( $urls );
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* If a Pantheon site is in Git mode, hide the Plugin installation functionality and show a notice.
|
||||
*/
|
||||
|
||||
if ( ! wp_is_writable( WP_PLUGIN_DIR ) ) {
|
||||
if ( ! defined( 'DISALLOW_FILE_MODS' ) ) {
|
||||
define( 'DISALLOW_FILE_MODS', true );
|
||||
}
|
||||
|
||||
add_action( 'admin_notices', '_pantheon_plugin_install_notice' );
|
||||
add_action( 'network_admin_notices', '_pantheon_plugin_install_notice' );
|
||||
}
|
||||
|
||||
function _pantheon_plugin_install_notice() {
|
||||
$screen = get_current_screen();
|
||||
// Only show this notice on the plugins page.
|
||||
if ( 'plugins' === $screen->id || 'plugins-network' === $screen->id ) { ?>
|
||||
<div class="update-nag notice notice-warning is-dismissible" style="margin: 5px 6em 15px 0;">
|
||||
<p style="font-size: 14px; margin: 0;">
|
||||
<?php
|
||||
// Translators: %s is a URL to the user's Pantheon Dashboard.
|
||||
echo wp_kses_post( sprintf( __( 'If you wish to update or add plugins using the WordPress UI, switch your site to SFTP mode from <a href="%s">your Pantheon dashboard</a>.', 'pantheon-systems' ), 'https://dashboard.pantheon.io/sites/' . $_ENV['PANTHEON_SITE'] ) );
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
/**
|
||||
* Pantheon MU Plugin Updates
|
||||
*
|
||||
* Handles modifying the default WordPress update behavior on Pantheon.
|
||||
*/
|
||||
|
||||
// If on Pantheon...
|
||||
if ( isset( $_ENV['PANTHEON_ENVIRONMENT'] ) ) {
|
||||
// Disable WordPress auto updates.
|
||||
if ( ! defined( 'WP_AUTO_UPDATE_CORE' ) ) {
|
||||
define( 'WP_AUTO_UPDATE_CORE', false );
|
||||
}
|
||||
|
||||
remove_action( 'wp_maybe_auto_update', 'wp_maybe_auto_update' );
|
||||
// Remove the default WordPress core update nag.
|
||||
add_action( 'admin_menu', '_pantheon_hide_update_nag' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default WordPress core update nag message.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function _pantheon_hide_update_nag() {
|
||||
remove_action( 'admin_notices', 'update_nag', 3 );
|
||||
remove_action( 'network_admin_notices', 'update_nag', 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns the current WordPress version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function _pantheon_get_current_wordpress_version(): string {
|
||||
include ABSPATH . WPINC . '/version.php';
|
||||
return $wp_version; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest WordPress version.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
function _pantheon_get_latest_wordpress_version(): ?string {
|
||||
$core_updates = get_core_updates();
|
||||
|
||||
if ( ! is_array( $core_updates ) || empty( $core_updates ) || ! property_exists( $core_updates[0], 'current' ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $core_updates[0]->current;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if WordPress core is at the latest version.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function _pantheon_is_wordpress_core_latest(): bool {
|
||||
$latest_wp_version = _pantheon_get_latest_wordpress_version();
|
||||
$wp_version = _pantheon_get_current_wordpress_version();
|
||||
|
||||
if ( null === $latest_wp_version ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true if our version is the latest.
|
||||
return version_compare( str_replace( '-src', '', $latest_wp_version ), str_replace( '-src', '', $wp_version ), '<=' ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if WordPress core is a pre-release version.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function _pantheon_is_wordpress_core_prerelease(): bool {
|
||||
$wp_version = _pantheon_get_current_wordpress_version();
|
||||
|
||||
// Return true if our version is a prerelease. Pre-releases are identified by a dash in the version number.
|
||||
return false !== strpos( $wp_version, '-' ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace WordPress core update nag EVERYWHERE with our own notice.
|
||||
* Use git upstream instead
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function _pantheon_upstream_update_notice() {
|
||||
$wp_version = _pantheon_get_current_wordpress_version();
|
||||
$screen = get_current_screen();
|
||||
// Translators: %s is a URL to the user's Pantheon Dashboard.
|
||||
$notice_message = sprintf( __( 'Check for updates on <a href="%s">your Pantheon dashboard</a>.', 'pantheon-systems' ), 'https://dashboard.pantheon.io/sites/' . $_ENV['PANTHEON_SITE'] );
|
||||
// Translators: %s is a URL to Pantheon's upstream updates documentation.
|
||||
$upstream_help_message = sprintf( __( 'For details on applying updates, see the <a href="%s">Applying Upstream Updates</a> documentation.', 'pantheon-systems' ), 'https://docs.pantheon.io/core-updates' );
|
||||
$update_help = __( 'If you need help, contact an administrator for your Pantheon organization.', 'pantheon-systems' );
|
||||
$div_class = esc_attr( 'update-nag notice notice-warning' );
|
||||
$div_style = esc_attr( 'display: table;' );
|
||||
$paragraph_style = esc_attr( 'font-size: 14px; font-weight: bold; margin: 0 0 0.5em 0;' );
|
||||
|
||||
if ( ! _pantheon_is_wordpress_core_latest() ) {
|
||||
// If WP core is out of date, alter the message and show the nag everywhere.
|
||||
// Translators: %s is a URL to the user's Pantheon Dashboard.
|
||||
$notice_message = sprintf( __( 'A new WordPress update is available! Please update from <a href="%s">your Pantheon dashboard</a>.', 'pantheon-systems' ), 'https://dashboard.pantheon.io/sites/' . $_ENV['PANTHEON_SITE'] );
|
||||
}
|
||||
|
||||
// If WP core is a pre-release, alter the message.
|
||||
if ( _pantheon_is_wordpress_core_prerelease() ) {
|
||||
$version = '<span style="font-weight: normal;">(' . $wp_version . ')</span>';
|
||||
$paragraph_style = esc_attr( 'font-size: 14px;' );
|
||||
// Translators: %s is the current WordPress version.
|
||||
$notice_message = sprintf( __( '<strong>You are using a development version of WordPress.</strong> %s', 'pantheon-systems' ), $version );
|
||||
// If we're on the Updates page, add a note about the Beta Tester plugin.
|
||||
if ( 'update-core' === $screen->id || 'update-core-network' === $screen->id ) {
|
||||
$notice_message .= '<br /><span style="font-weight: normal;">';
|
||||
$notice_message .= __( 'You are responsible for keeping WordPress up-to-date. Pantheon updates to WordPress will not appear in the dashboard as long as you\'re using a pre-release version. If you are using the Beta Tester plugin, you must have your site in SFTP mode to get the latest updates to your Pantheon Dev environment.', 'pantheon-systems' );
|
||||
}
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="<?php echo esc_attr( $div_class ); ?>" style="<?php echo esc_attr( $div_style ); ?>">
|
||||
<p style="<?php echo esc_attr( $paragraph_style ); ?>">
|
||||
<?php echo wp_kses_post( $notice_message ); ?>
|
||||
</p>
|
||||
<?php if ( ! _pantheon_is_wordpress_core_prerelease() ) : ?>
|
||||
<?php echo wp_kses_post( $upstream_help_message ); ?>
|
||||
<br />
|
||||
<?php echo wp_kses_post( $update_help ); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
$notice_html = ob_get_clean();
|
||||
// If a WP core update is not detected, only show the nag on the updates page.
|
||||
if ( ! _pantheon_is_wordpress_core_latest() || 'update-core' === $screen->id || 'update-core-network' === $screen->id ) {
|
||||
// Escaping is handled above when we're buffering the output, so we can ignore it here.
|
||||
echo $notice_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Pantheon specific WordPress update admin notice.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function _pantheon_register_upstream_update_notice() {
|
||||
// Only register notice if we are on Pantheon and this is not a WordPress Ajax request.
|
||||
if ( isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && ! wp_doing_ajax() ) {
|
||||
add_action( 'admin_notices', '_pantheon_upstream_update_notice' );
|
||||
add_action( 'network_admin_notices', '_pantheon_upstream_update_notice' );
|
||||
}
|
||||
}
|
||||
add_action( 'admin_init', '_pantheon_register_upstream_update_notice' );
|
||||
|
||||
/**
|
||||
* Return zero updates and current time as last checked time.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
function _pantheon_disable_wp_updates(): object {
|
||||
$wp_version = _pantheon_get_current_wordpress_version();
|
||||
return (object) [
|
||||
'updates' => [],
|
||||
'version_checked' => $wp_version, // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
|
||||
'last_checked' => time(),
|
||||
];
|
||||
}
|
||||
|
||||
// In the Test and Live environments, clear plugin/theme update notifications.
|
||||
// Users must check a dev or multidev environment for updates.
|
||||
if ( isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && in_array( $_ENV['PANTHEON_ENVIRONMENT'], [ 'test', 'live' ], true ) && ( php_sapi_name() !== 'cli' ) ) {
|
||||
|
||||
// Disable Plugin Updates.
|
||||
remove_action( 'load-update-core.php', 'wp_update_plugins' );
|
||||
add_filter( 'pre_site_transient_update_plugins', '_pantheon_disable_wp_updates' );
|
||||
|
||||
// Disable Theme Updates.
|
||||
remove_action( 'load-update-core.php', 'wp_update_themes' );
|
||||
add_filter( 'pre_site_transient_update_themes', '_pantheon_disable_wp_updates' );
|
||||
}
|
||||
54
wp/wp-content/mu-plugins/pantheon-mu-plugin/pantheon.php
Normal file
54
wp/wp-content/mu-plugins/pantheon-mu-plugin/pantheon.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Pantheon
|
||||
* Plugin URI: https://pantheon.io/
|
||||
* Description: Building on Pantheon's and WordPress's strengths, together.
|
||||
* Version: 1.2.1
|
||||
* Author: Pantheon
|
||||
* Author URI: https://pantheon.io/
|
||||
*
|
||||
* @package pantheon
|
||||
*/
|
||||
|
||||
define( 'PANTHEON_MU_PLUGIN_VERSION', '1.2.1' );
|
||||
|
||||
if ( isset( $_ENV['PANTHEON_ENVIRONMENT'] ) ) {
|
||||
|
||||
require_once 'inc/pantheon-page-cache.php';
|
||||
if ( ! defined( 'DISABLE_PANTHEON_UPDATE_NOTICES' ) || ! DISABLE_PANTHEON_UPDATE_NOTICES ) {
|
||||
require_once 'inc/pantheon-updates.php';
|
||||
}
|
||||
if ( ! defined( 'RETURN_TO_PANTHEON_BUTTON' ) || RETURN_TO_PANTHEON_BUTTON ) {
|
||||
require_once 'inc/pantheon-login-form-mods.php';
|
||||
}
|
||||
if ( 'dev' === $_ENV['PANTHEON_ENVIRONMENT'] && function_exists( 'wp_is_writable' ) ) {
|
||||
require_once 'inc/pantheon-plugin-install-notice.php';
|
||||
}
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
require_once 'inc/cli.php';
|
||||
}
|
||||
if ( ! defined( 'FS_METHOD' ) ) {
|
||||
/**
|
||||
* When this constant is not set, WordPress writes and then deletes a
|
||||
* temporary file to determine if it has direct access to the filesystem,
|
||||
* which we already know to be the case. This multiplies filesystem
|
||||
* operations and can degrade performance of the filesystem as a whole in
|
||||
* the case of large sites that do a lot of filesystem operations.
|
||||
* Setting this constant to 'direct' tells WordPress to assume it has
|
||||
* direct access and skip creating the extra temporary file.
|
||||
*/
|
||||
define( 'FS_METHOD', 'direct' );
|
||||
}
|
||||
// When developing a WordPress Multisite locally, ensure that this constant is set.
|
||||
// This will set the Multisite variable in all Pantheon environments.
|
||||
if ( getenv( 'FRAMEWORK' ) === 'wordpress_network' && ! defined( 'WP_ALLOW_MULTISITE' ) ) {
|
||||
define( 'WP_ALLOW_MULTISITE', true );
|
||||
}
|
||||
if ( defined( 'WP_ALLOW_MULTISITE' ) && WP_ALLOW_MULTISITE ) {
|
||||
if ( defined( 'MULTISITE' ) && MULTISITE ) {
|
||||
require_once 'inc/pantheon-network-setup.php';
|
||||
} else {
|
||||
require_once 'inc/pantheon-multisite-finalize.php';
|
||||
}
|
||||
}
|
||||
} // Ensuring that this is on Pantheon.
|
||||
@@ -80,9 +80,15 @@
|
||||
var data = [];
|
||||
|
||||
$( this ).closest( 'form' ).find( '[data-config-field]' ).each( function() {
|
||||
var val = $( this ).val();
|
||||
|
||||
if ( $( this ).is( '[type=checkbox]' ) ) {
|
||||
val = $( this ).is( ':checked' ) ? 1 : 0;
|
||||
}
|
||||
|
||||
data.push( {
|
||||
'name': $( this ).attr( 'name' ).replace( /^wpcf7-/, '' ).replace( /-/g, '_' ),
|
||||
'value': $( this ).val()
|
||||
'value': val
|
||||
} );
|
||||
} );
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ function wpcf7_enqueue_block_editor_assets() {
|
||||
'contact-form-7-block-editor',
|
||||
sprintf(
|
||||
'window.wpcf7 = {contactForms:%s};',
|
||||
json_encode( $contact_forms )
|
||||
wp_json_encode( $contact_forms )
|
||||
),
|
||||
'before'
|
||||
);
|
||||
|
||||
@@ -275,6 +275,17 @@ function wpcf7_sanitize_unit_tag( $tag ) {
|
||||
function wpcf7_antiscript_file_name( $filename ) {
|
||||
$filename = wp_basename( $filename );
|
||||
|
||||
// Apply part of protection logic from sanitize_file_name().
|
||||
$filename = str_replace(
|
||||
array(
|
||||
'?', '[', ']', '/', '\\', '=', '<', '>', ':', ';', ',', "'", '"',
|
||||
'&', '$', '#', '*', '(', ')', '|', '~', '`', '!', '{', '}',
|
||||
'%', '+', '’', '«', '»', '”', '“', chr( 0 )
|
||||
),
|
||||
'',
|
||||
$filename
|
||||
);
|
||||
|
||||
$filename = preg_replace( '/[\r\n\t -]+/', '-', $filename );
|
||||
$filename = preg_replace( '/[\pC\pZ]+/iu', '', $filename );
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class WPCF7_SWV_FileRule extends WPCF7_SWV_Rule {
|
||||
$acceptable_filetypes = array();
|
||||
|
||||
foreach ( (array) $this->get_property( 'accept' ) as $accept ) {
|
||||
if ( false === strpos( $accept, '/' ) ) {
|
||||
if ( preg_match( '/^\.[a-z0-9]+$/i', $accept ) ) {
|
||||
$acceptable_filetypes[] = strtolower( $accept );
|
||||
} else {
|
||||
foreach ( wpcf7_convert_mime_to_ext( $accept ) as $ext ) {
|
||||
|
||||
@@ -247,7 +247,7 @@ class WPCF7_ConstantContact extends WPCF7_Service_OAuth2 {
|
||||
'Accept' => 'application/json',
|
||||
'Content-Type' => 'application/json; charset=utf-8',
|
||||
),
|
||||
'body' => json_encode( $properties ),
|
||||
'body' => wp_json_encode( $properties ),
|
||||
);
|
||||
|
||||
$response = $this->remote_request( $endpoint, $request );
|
||||
|
||||
@@ -336,7 +336,7 @@ trait WPCF7_Sendinblue_API {
|
||||
'Content-Type' => 'application/json; charset=utf-8',
|
||||
'API-Key' => $this->get_api_key(),
|
||||
),
|
||||
'body' => json_encode( $properties ),
|
||||
'body' => wp_json_encode( $properties ),
|
||||
);
|
||||
|
||||
$response = wp_remote_post( $endpoint, $request );
|
||||
@@ -364,7 +364,7 @@ trait WPCF7_Sendinblue_API {
|
||||
'Content-Type' => 'application/json; charset=utf-8',
|
||||
'API-Key' => $this->get_api_key(),
|
||||
),
|
||||
'body' => json_encode( $properties ),
|
||||
'body' => wp_json_encode( $properties ),
|
||||
);
|
||||
|
||||
$response = wp_remote_post( $endpoint, $request );
|
||||
|
||||
@@ -61,7 +61,7 @@ class WPCF7_Stripe_API {
|
||||
$headers = array(
|
||||
'Authorization' => sprintf( 'Bearer %s', $this->secret ),
|
||||
'Stripe-Version' => self::api_version,
|
||||
'X-Stripe-Client-User-Agent' => json_encode( $ua ),
|
||||
'X-Stripe-Client-User-Agent' => wp_json_encode( $ua ),
|
||||
'User-Agent' => sprintf(
|
||||
'%1$s/%2$s (%3$s)',
|
||||
self::app_name,
|
||||
|
||||
@@ -5,7 +5,7 @@ Tags: contact, form, contact form, feedback, email, ajax, captcha, akismet, mult
|
||||
Requires at least: 6.2
|
||||
Requires PHP: 7.4
|
||||
Tested up to: 6.4
|
||||
Stable tag: 5.8.3
|
||||
Stable tag: 5.8.5
|
||||
License: GPLv2 or later
|
||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
@@ -78,6 +78,14 @@ Do you have questions or issues with Contact Form 7? Use these support channels
|
||||
|
||||
For more information, see [Releases](https://contactform7.com/category/releases/).
|
||||
|
||||
= 5.8.5 =
|
||||
|
||||
[https://contactform7.com/contact-form-7-585/](https://contactform7.com/contact-form-7-585/)
|
||||
|
||||
= 5.8.4 =
|
||||
|
||||
[https://contactform7.com/contact-form-7-584/](https://contactform7.com/contact-form-7-584/)
|
||||
|
||||
= 5.8.3 =
|
||||
|
||||
[https://contactform7.com/contact-form-7-583/](https://contactform7.com/contact-form-7-583/)
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
* Author URI: https://ideasilo.wordpress.com/
|
||||
* License: GPL v2 or later
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
* Version: 5.8.3
|
||||
* Version: 5.8.5
|
||||
* Requires at least: 6.2
|
||||
* Requires PHP: 7.4
|
||||
*/
|
||||
|
||||
define( 'WPCF7_VERSION', '5.8.3' );
|
||||
define( 'WPCF7_VERSION', '5.8.5' );
|
||||
|
||||
define( 'WPCF7_REQUIRED_WP_VERSION', '6.2' );
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
.imagify-account,.imagify-account-link{padding-right:15px}.imagify-meteo-icon{display:inline-block;height:38px;vertical-align:middle;margin-right:10px}.imagify-user-plan{color:#40b1d0}.imagify-meteo-title.imagify-meteo-title{color:#fff;font-size:17px}.imagify-space-left>p{color:#fff}#wp-admin-bar-imagify-profile [class^=imagify-bar-]{position:relative;height:1.5em;width:100%;background:#60758d;color:#fff;font-size:10px}#wp-admin-bar-imagify-profile .imagify-progress{height:1.5em;font-size:1em}.imagify-progress{-webkit-transition:width .3s;-o-transition:width .3s;transition:width .3s}.imagify-bar-positive .imagify-progress{background:#8cc152}.imagify-bar-positive .imagify-barnb{color:#8cc152}.imagify-bar-negative .imagify-progress{background:#73818c}.imagify-bar-negative .imagify-barnb{color:#73818c}.imagify-bar-neutral .imagify-progress{background:#f5a623}.imagify-space-left .imagify-bar-negative .imagify-progress{background:#d0021b}#wpadminbar #wp-admin-bar-imagify-profile *{line-height:1.5;white-space:initial}#wpadminbar #wp-admin-bar-imagify .ab-submenu{padding-bottom:0}#wpadminbar #wp-admin-bar-imagify-profile .ab-item{height:auto;padding:0 13px}#wpadminbar #wp-admin-bar-imagify-profile{min-width:200px;padding:15px 0 10px;margin-top:.7em;background:#222}#wp-admin-bar-imagify .dashicons{font-family:dashicons;font-size:18px;vertical-align:middle;margin:0 5px 0 0}#wp-admin-bar-imagify .button-text{display:inline-block;vertical-align:middle}#wp-admin-bar-imagify .imagify-abq-row{display:table;width:100%}#wp-admin-bar-imagify .imagify-abq-row+.imagify-abq-row{margin-top:.75em}#wp-admin-bar-imagify .imagify-abq-row>*{display:table-cell}#wp-admin-bar-imagify-profile .imagify-meteo-icon{padding-right:7px}#wp-admin-bar-imagify-profile .imagify-meteo-icon img{width:37px}#wp-admin-bar-imagify-profile .imagify-meteo-title{font-size:17px}#wp-admin-bar-imagify-profile .imagify-meteo-subs{color:#72889f}#wpadminbar #wp-admin-bar-imagify-profile strong{font-weight:700}#wpadminbar #wp-admin-bar-imagify-profile .imagify-user-plan,#wpadminbar #wp-admin-bar-imagify-profile a{padding:0;color:#40b1d0}#wpadminbar #wp-admin-bar-imagify-profile .imagify-account-link{display:table}#wpadminbar #wp-admin-bar-imagify-profile .imagify-account-link>*{display:table-cell}#wpadminbar #wp-admin-bar-imagify-profile .imagify-space-left{max-width:210px;min-width:210px;width:210px}#wpadminbar #wp-admin-bar-imagify-profile .imagify-space-left p{font-size:12px}#wp-admin-bar-imagify-profile .imagify-error,#wp-admin-bar-imagify-profile .imagify-warning{padding:10px;margin:0 -13px -13px}#wp-admin-bar-imagify-profile .imagify-error p+p,#wp-admin-bar-imagify-profile .imagify-warning p+p{margin-top:.5em}#wp-admin-bar-imagify-profile .imagify-error p+p+p,#wp-admin-bar-imagify-profile .imagify-warning p+p+p{margin-top:1em}#wpadminbar #wp-admin-bar-imagify-profile .imagify-btn-ghost{display:inline-block;height:auto;padding:7px 10px;border:1px solid #fff;text-align:center;background:0 0;color:#fff;border-radius:3px;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}#wpadminbar #wp-admin-bar-imagify-profile .imagify-btn-ghost:focus,#wpadminbar #wp-admin-bar-imagify-profile .imagify-btn-ghost:hover{background:#fff;color:#888}#wpadminbar .imagify-warning *{background:#f5a623;color:#fff;text-shadow:0 0 2px rgba(0,0,0,.2)}
|
||||
.imagify-account,.imagify-account-link{padding-right:15px}.imagify-meteo-icon{display:inline-block;height:38px;vertical-align:middle;margin-right:10px}.imagify-user-plan{color:#40b1d0}.imagify-meteo-title.imagify-meteo-title{color:#fff;font-size:17px}.imagify-space-left>p{color:#fff}#wp-admin-bar-imagify-profile [class^=imagify-bar-]{position:relative;height:1.5em;width:100%;background:#60758d;color:#fff;font-size:10px}#wp-admin-bar-imagify-profile .imagify-progress{height:1.5em;font-size:1em}.imagify-progress{-webkit-transition:width .3s;-o-transition:width .3s;transition:width .3s}.imagify-bar-positive .imagify-progress{background:#8cc152}.imagify-bar-positive .imagify-barnb{color:#8cc152}.imagify-bar-negative .imagify-progress{background:#73818c}.imagify-bar-negative .imagify-barnb{color:#73818c}.imagify-bar-neutral .imagify-progress{background:#f5a623}.imagify-space-left .imagify-bar-negative .imagify-progress{background:#d0021b}#wpadminbar #wp-admin-bar-imagify-profile *{line-height:1.5;white-space:initial}#wpadminbar #wp-admin-bar-imagify .ab-submenu{padding-bottom:0}#wpadminbar #wp-admin-bar-imagify-profile .ab-item{height:auto;padding:0 13px}#wpadminbar #wp-admin-bar-imagify-profile{min-width:200px;padding:15px 0 10px;margin-top:.7em;background:#222}#wp-admin-bar-imagify .dashicons{font-family:dashicons;font-size:18px;vertical-align:middle;margin:0 5px 0 0}#wp-admin-bar-imagify .button-text{display:inline-block;vertical-align:middle}#wp-admin-bar-imagify .imagify-abq-row{display:table;width:100%}#wp-admin-bar-imagify .imagify-abq-row+.imagify-abq-row{margin-top:.75em}#wp-admin-bar-imagify .imagify-abq-row>*{display:table-cell}#wp-admin-bar-imagify-profile .imagify-meteo-icon{padding-right:7px}#wp-admin-bar-imagify-profile .imagify-meteo-icon img{width:37px}#wp-admin-bar-imagify-profile .imagify-meteo-title{font-size:17px}#wp-admin-bar-imagify-profile .imagify-meteo-subs{color:#72889f}#wpadminbar #wp-admin-bar-imagify-profile strong{font-weight:700}#wpadminbar #wp-admin-bar-imagify-profile .imagify-user-plan,#wpadminbar #wp-admin-bar-imagify-profile a{padding:0;color:#40b1d0}#wpadminbar #wp-admin-bar-imagify-profile .imagify-account-link{display:table}#wpadminbar #wp-admin-bar-imagify-profile .imagify-account-link>*{display:table-cell}#wpadminbar #wp-admin-bar-imagify-profile .imagify-space-left{max-width:210px;min-width:210px;width:210px}#wpadminbar #wp-admin-bar-imagify-profile .imagify-space-left p{font-size:12px}#wp-admin-bar-imagify-profile .imagify-error,#wp-admin-bar-imagify-profile .imagify-warning{padding:10px;margin:0 -13px -13px}#wp-admin-bar-imagify-profile .imagify-error p+p,#wp-admin-bar-imagify-profile .imagify-warning p+p{margin-top:.5em}#wp-admin-bar-imagify-profile .imagify-error p+p+p,#wp-admin-bar-imagify-profile .imagify-warning p+p+p{margin-top:1em}#wpadminbar #wp-admin-bar-imagify-profile .imagify-btn-ghost{display:inline-block;height:auto;padding:7px 10px;border:1px solid #fff;text-align:center;background:0 0;color:#fff;border-radius:3px;-webkit-transition:all .275s;-o-transition:all .275s;transition:all .275s}#wpadminbar #wp-admin-bar-imagify-profile .imagify-btn-ghost:focus,#wpadminbar #wp-admin-bar-imagify-profile .imagify-btn-ghost:hover{background:#fff;color:#888}#wpadminbar .imagify-warning *{background:#f5a623;color:#fff;text-shadow:0 0 2px rgba(0,0,0,.2)}#wp-admin-bar-imagify-profile .imagify-upsell-admin-bar{position:relative;background:#c51161;margin:10px -13px -10px -13px;padding:20px}#wp-admin-bar-imagify-profile .imagify-upsell-admin-bar p{color:#fff}#wp-admin-bar-imagify-profile a.imagify-upsell-admin-bar-button{display:block;height:auto!important;border:1px solid #fff;border-radius:5px;color:#fff!important;padding:5px 10px!important;text-align:center;text-decoration:none;margin-top:10px}#wpadminbar #wp-admin-bar-imagify-profile a.imagify-upsell-dismiss{display:inline!important;height:auto!important}#wpadminbar #wp-admin-bar-imagify-profile .imagify-upsell-dismiss::before{position:absolute;top:5px;right:10px;content:"\2715";color:#fff}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
!function(n){n(".imagify-notice-dismiss").on("click.imagify",function(i){var e=n(this),t=e.parents(".imagify-welcome, .imagify-notice, .imagify-rkt-notice"),e=e.attr("href");i.preventDefault(),t.fadeTo(100,0,function(){n(this).slideUp(100,function(){n(this).remove()})}),n.get(e.replace("admin-post.php","admin-ajax.php"))})}(jQuery,(document,window)),function(n,a){n("#imagify-signup").on("click.imagify",function(i){i.preventDefault(),swal({title:imagifyNotices.labels.signupTitle,html:imagifyNotices.labels.signupText,confirmButtonText:imagifyNotices.labels.signupConfirmButtonText,input:"email",padding:0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(t){return new Promise(function(i,e){""!==n.trim(t)&&t?i():e(imagifyNotices.labels.signupErrorEmptyEmail)})},preConfirm:function(i){return new Promise(function(e,t){setTimeout(function(){n.get(ajaxurl+a.imagify.concat+"action=imagify_signup&email="+i+"&imagifysignupnonce="+n("#imagifysignupnonce").val()).done(function(i){i.success?e():t(i.data)})},2e3)})}}).then(function(){swal({title:imagifyNotices.labels.signupSuccessTitle,html:imagifyNotices.labels.signupSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"})})}),n("#imagify-save-api-key").on("click.imagify",function(i){i.preventDefault(),swal({title:imagifyNotices.labels.saveApiKeyTitle,html:imagifyNotices.labels.saveApiKeyText,confirmButtonText:imagifyNotices.labels.saveApiKeyConfirmButtonText,input:"text",padding:0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(t){return new Promise(function(i,e){""!==n.trim(t)&&t?i():e(imagifyNotices.labels.ApiKeyErrorEmpty)})},preConfirm:function(i){return new Promise(function(e,t){n.get(ajaxurl+a.imagify.concat+"action=imagify_check_api_key_validity&api_key="+i+"&imagifycheckapikeynonce="+n("#imagifycheckapikeynonce").val()).done(function(i){i.success?e():t(i.data)})})}}).then(function(){swal({title:imagifyNotices.labels.ApiKeyCheckSuccessTitle,html:imagifyNotices.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"})})})}(jQuery,(document,window));
|
||||
!function(n){n(".imagify-notice-dismiss").on("click.imagify",function(i){var e=n(this),t=e.parents(".imagify-welcome, .imagify-notice, .imagify-rkt-notice, .imagify-upsell, .imagify-upsell-admin-bar"),e=e.attr("href");i.preventDefault(),t.fadeTo(100,0,function(){n(this).slideUp(100,function(){n(this).remove()})}),n.get(e.replace("admin-post.php","admin-ajax.php"))})}(jQuery,(document,window)),function(n,a){n("#imagify-signup").on("click.imagify",function(i){i.preventDefault(),swal({title:imagifyNotices.labels.signupTitle,html:imagifyNotices.labels.signupText,confirmButtonText:imagifyNotices.labels.signupConfirmButtonText,input:"email",padding:0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(t){return new Promise(function(i,e){""!==n.trim(t)&&t?i():e(imagifyNotices.labels.signupErrorEmptyEmail)})},preConfirm:function(i){return new Promise(function(e,t){setTimeout(function(){n.get(ajaxurl+a.imagify.concat+"action=imagify_signup&email="+i+"&imagifysignupnonce="+n("#imagifysignupnonce").val()).done(function(i){i.success?e():t(i.data)})},2e3)})}}).then(function(){swal({title:imagifyNotices.labels.signupSuccessTitle,html:imagifyNotices.labels.signupSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"})})}),n("#imagify-save-api-key").on("click.imagify",function(i){i.preventDefault(),swal({title:imagifyNotices.labels.saveApiKeyTitle,html:imagifyNotices.labels.saveApiKeyText,confirmButtonText:imagifyNotices.labels.saveApiKeyConfirmButtonText,input:"text",padding:0,showLoaderOnConfirm:!0,customClass:"imagify-sweet-alert imagify-sweet-alert-signup",inputValidator:function(t){return new Promise(function(i,e){""!==n.trim(t)&&t?i():e(imagifyNotices.labels.ApiKeyErrorEmpty)})},preConfirm:function(i){return new Promise(function(e,t){n.get(ajaxurl+a.imagify.concat+"action=imagify_check_api_key_validity&api_key="+i+"&imagifycheckapikeynonce="+n("#imagifycheckapikeynonce").val()).done(function(i){i.success?e():t(i.data)})})}}).then(function(){swal({title:imagifyNotices.labels.ApiKeyCheckSuccessTitle,html:imagifyNotices.labels.ApiKeyCheckSuccessText,type:"success",padding:0,customClass:"imagify-sweet-alert"})})})}(jQuery,(document,window));
|
||||
@@ -3,7 +3,7 @@
|
||||
* Plugin Name: Imagify
|
||||
* Plugin URI: https://wordpress.org/plugins/imagify/
|
||||
* Description: Dramatically reduce image file sizes without losing quality, make your website load faster, boost your SEO and save money on your bandwidth using Imagify, the new most advanced image optimization tool.
|
||||
* Version: 2.1.3
|
||||
* Version: 2.1.3.1
|
||||
* Requires at least: 5.3
|
||||
* Requires PHP: 7.0
|
||||
* Author: Imagify – Optimize Images & Convert WebP
|
||||
@@ -19,7 +19,7 @@
|
||||
defined( 'ABSPATH' ) || die( 'Cheatin’ uh?' );
|
||||
|
||||
// Imagify defines.
|
||||
define( 'IMAGIFY_VERSION', '2.1.3' );
|
||||
define( 'IMAGIFY_VERSION', '2.1.3.1' );
|
||||
define( 'IMAGIFY_SLUG', 'imagify' );
|
||||
define( 'IMAGIFY_FILE', __FILE__ );
|
||||
define( 'IMAGIFY_PATH', realpath( plugin_dir_path( IMAGIFY_FILE ) ) . '/' );
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
=== Imagify – Optimize Images & Convert WebP | Compress Images Easily ===
|
||||
Contributors: wp_rocket, imagify
|
||||
Tags: optimize images, convert webp, webp converter, image optimization, compress images, image compressor, resize images, reduce image size, performance, image optimizer, core web vitals, best image optimization plugin
|
||||
Tested up to: 6.3
|
||||
Stable tag: 2.1.3
|
||||
Tested up to: 6.4
|
||||
Stable tag: 2.1.3.1
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
@@ -258,6 +258,9 @@ You can report any security bugs found in the source code of the site-reviews pl
|
||||
4. Other Media Page
|
||||
|
||||
== Changelog ==
|
||||
= 2.1.3.1 =
|
||||
- Bugfix: missing styling on some banners when using minified versions of the CSS files (#765)
|
||||
|
||||
= 2.1.3 =
|
||||
- Enhancement: Update chart.js (#742)
|
||||
- Enhancement: Improve messaging around WebP images when they are larger than the original (#751)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php return array(
|
||||
'root' => array(
|
||||
'name' => 'wp-media/imagify-plugin',
|
||||
'pretty_version' => 'v2.1.3',
|
||||
'version' => '2.1.3.0',
|
||||
'reference' => '58a54d5f7381cc9884874f51021a0c791965fc05',
|
||||
'pretty_version' => 'v2.1.3.1',
|
||||
'version' => '2.1.3.1',
|
||||
'reference' => '82a34afe494abd2ba229285f871ab23239428a20',
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@@ -29,9 +29,9 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'wp-media/imagify-plugin' => array(
|
||||
'pretty_version' => 'v2.1.3',
|
||||
'version' => '2.1.3.0',
|
||||
'reference' => '58a54d5f7381cc9884874f51021a0c791965fc05',
|
||||
'pretty_version' => 'v2.1.3.1',
|
||||
'version' => '2.1.3.1',
|
||||
'reference' => '82a34afe494abd2ba229285f871ab23239428a20',
|
||||
'type' => 'wordpress-plugin',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: fabrizio pera
|
||||
* Date: 22/11/16
|
||||
* Time: 10:48
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
die( '-1' );
|
||||
}
|
||||
@@ -24,13 +19,8 @@ if(!class_exists('IperCampaignController')){
|
||||
const kCOOKIE_ID_FIVE9 = "SESSfive9";
|
||||
const kCOOKIE_WEB_PROMOTION_TEXT = "SESSpromotion";
|
||||
const kCOOKIE_PHONE = "SESScampaignphone";
|
||||
const KCOOKIE_ControlPhone = "SESScontrolphone";
|
||||
const KCOOKIE_CanaryPhone = "SESScanaryphone";
|
||||
const kCOOKIE_EXPIRE = 15552000; // 6 months (3600 * 24 * 30 * 6)
|
||||
const KCOOKIE_WEB_TOP_BAR = "SESStopoffer";
|
||||
const KCOOKIE_Google_KW = "SESSgooglekw";
|
||||
const KCOOKIE_AB_Test = "SESSabtest";
|
||||
const KCOOKIE_ConfirmationPageText = "SESSconfirmationpagetext";
|
||||
|
||||
|
||||
protected static $instance;
|
||||
public $testVar;
|
||||
@@ -106,7 +96,6 @@ if(!class_exists('IperCampaignController')){
|
||||
return $phonenumber;
|
||||
}
|
||||
|
||||
|
||||
public static function getCampaignID(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::kCOOKIE_ID])){
|
||||
return $_COOKIE[self::kCOOKIE_ID];
|
||||
@@ -126,48 +115,8 @@ if(!class_exists('IperCampaignController')){
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static function getGoogle_KW(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::kCOOKIE_Google_KW])){
|
||||
return $_COOKIE[self::KCOOKIE_Google_KW];
|
||||
}
|
||||
if(!empty($_SESSION[self::KCOOKIE_Google_KW])){
|
||||
return $_SESSION[self::KCOOKIE_Google_KW];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getAB_Test(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::KCOOKIE_AB_Test])){
|
||||
return $_COOKIE[self::KCOOKIE_AB_Test];
|
||||
}
|
||||
if(!empty($_SESSION[self::KCOOKIE_AB_Test])){
|
||||
return $_SESSION[self::KCOOKIE_AB_Test];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getCanaryPhone(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::KCOOKIE_CanaryPhone])){
|
||||
return $_COOKIE[self::KCOOKIE_CanaryPhone];
|
||||
}
|
||||
if(!empty($_SESSION[self::KCOOKIE_CanaryPhone])){
|
||||
return $_SESSION[self::KCOOKIE_CanaryPhone];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getControlPhone(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::KCOOKIE_ControlPhone])){
|
||||
return $_COOKIE[self::KCOOKIE_ControlPhone];
|
||||
}
|
||||
if(!empty($_SESSION[self::KCOOKIE_ControlPhone])){
|
||||
return $_SESSION[self::KCOOKIE_ControlPhone];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static function getWebPromotionText(){
|
||||
public static function getWebPromotionText(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::kCOOKIE_WEB_PROMOTION_TEXT])){
|
||||
return $_COOKIE[self::kCOOKIE_WEB_PROMOTION_TEXT];
|
||||
}
|
||||
@@ -176,25 +125,7 @@ if(!class_exists('IperCampaignController')){
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public static function getConfirmationPageText(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::KCOOKIE_ConfirmationPageText])){
|
||||
return $_COOKIE[self::KCOOKIE_ConfirmationPageText];
|
||||
}
|
||||
if(!empty($_SESSION[self::KCOOKIE_ConfirmationPageText])){
|
||||
return $_SESSION[self::KCOOKIE_ConfirmationPageText];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static function getCampaignSO(){
|
||||
if(!empty($_COOKIE) && !empty($_COOKIE[self::KCOOKIE_WEB_TOP_BAR])){
|
||||
return $_COOKIE[self::KCOOKIE_WEB_TOP_BAR];
|
||||
}
|
||||
if(!empty($_SESSION[self::KCOOKIE_WEB_TOP_BAR])){
|
||||
return $_SESSION[self::KCOOKIE_WEB_TOP_BAR];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function get_phone_number(){
|
||||
|
||||
$phoneNumber = get_option('cta_tel',true);
|
||||
@@ -239,32 +170,20 @@ if(!class_exists('IperCampaignController')){
|
||||
return false;
|
||||
}
|
||||
|
||||
public function setCampaign($id="",$phone="",$id_five_9="",$WebPromotionText="",$WebTopBarSpecialOffer="",$Google_KW, $ABTest, $ConfirmationPageText="",$CanaryPhone="",$ControlPhone=""){
|
||||
public function setCampaign($id="",$phone="",$id_five_9="",$WebPromotionText=""){
|
||||
|
||||
setcookie(self::kCOOKIE_ID, $id, 0,'/');
|
||||
setcookie(self::kCOOKIE_PHONE, $phone, 0,'/');
|
||||
setcookie(self::KCOOKIE_CanaryPhone, $CanaryPhone , 0,'/');
|
||||
setcookie(self::KCOOKIE_ControlPhone, $ControlPhone , 0,'/');
|
||||
setcookie(self::kCOOKIE_ID_FIVE9, $id_five_9, 0,'/');
|
||||
setcookie(self::kCOOKIE_WEB_PROMOTION_TEXT, $WebPromotionText , 0,'/');
|
||||
setcookie(self::KCOOKIE_WEB_TOP_BAR, $WebTopBarSpecialOffer , 0,'/');
|
||||
setcookie(self::KCOOKIE_Google_KW, $Google_KW , 0,'/');
|
||||
setcookie(self::KCOOKIE_AB_Test, $ABTest , 0,'/');
|
||||
setcookie(self::KCOOKIE_ConfirmationPageText, $ConfirmationPageText , 0,'/');
|
||||
if(!session_id()){
|
||||
session_start();
|
||||
}
|
||||
|
||||
$_SESSION[self::kCOOKIE_ID]=$id;
|
||||
$_SESSION[self::kCOOKIE_PHONE]=$phone;
|
||||
$_SESSION[self::KCOOKIE_CanaryPhone]=$CanaryPhone;
|
||||
$_SESSION[self::KCOOKIE_ControlPhone]=$ControlPhone;
|
||||
$_SESSION[self::kCOOKIE_ID_FIVE9]=$id_five_9;
|
||||
$_SESSION[self::kCOOKIE_WEB_PROMOTION_TEXT]=$WebPromotionText;
|
||||
$_SESSION[self::KCOOKIE_WEB_TOP_BAR]=$WebTopBarSpecialOffer;
|
||||
$_SESSION[self::KCOOKIE_Google_KW]=$Google_KW;
|
||||
$_SESSION[self::KCOOKIE_AB_Test]=$ABTest;
|
||||
$_SESSION[self::KCOOKIE_ConfirmationPageText]=$ConfirmationPageText;
|
||||
}
|
||||
|
||||
public function activate(){
|
||||
@@ -300,19 +219,12 @@ if(!class_exists('IperCampaignController')){
|
||||
$CampaignID = $single->CampaignID;
|
||||
$StartDate = $single->StartDate;
|
||||
$PhoneNumber = $single->PhoneNumber;
|
||||
$CanaryPhone = $single->CanaryPhoneNumber;
|
||||
$ControlPhone = $single->ControlPhoneNumber;
|
||||
$LandingURL = $single->LandingURL;
|
||||
$FriendlyURL = $single->FriendlyURL;
|
||||
$EndDate = $single->EndDate;
|
||||
$CampaignName = $single->CampaignName;
|
||||
$Five9CallbackCampaign = $single->Five9CallbackCampaign;
|
||||
$WebPromotionText = $single->WebPromotionText;//fill campaign field
|
||||
$WebTopBarSpecialOffer = $single->WebTopBarSpecialOffer;
|
||||
$Google_KW = $single->GoogleKW;
|
||||
$ABTest = $single->ABTest;
|
||||
$ConfirmationPageText = $single->ConfirmationPageText;
|
||||
|
||||
|
||||
$postname = str_replace(get_bloginfo('wpurl'),"",$FriendlyURL);
|
||||
|
||||
@@ -343,19 +255,13 @@ if(!class_exists('IperCampaignController')){
|
||||
IperCptCampaign::kMETA_CAMPAIGN_ID => $CampaignID,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_START_DATE => $StartDate,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_PHONE => $PhoneNumber,
|
||||
IperCptCampaign::KMETA_CanaryPhone => $CanaryPhone,//pull text from sales force
|
||||
IperCptCampaign::KMETA_ControlPhone => $ControlPhone,//pull text from sales force
|
||||
IperCptCampaign::kMETA_CAMPAIGN_LANDING_URL => $LandingURL,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_SHORT_URL => $FriendlyURL,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_END_DATE => $EndDate,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_NAME => $CampaignName,
|
||||
IperCptCampaign::kMETA_FIVE9 => $Five9CallbackCampaign,
|
||||
IperCptCampaign::kMETA_WEB_PROMOTION_TEXT => $WebPromotionText,//pull text from sales force
|
||||
IperCptCampaign::KMETA_WEB_TOP_BAR => $WebTopBarSpecialOffer,//pull text from sales force
|
||||
IperCptCampaign::KMETA_Google_KW => $Google_KW,//pull text from sales force
|
||||
IperCptCampaign::KMETA_AB_Test => $ABTest,//pull text from sales force
|
||||
IperCptCampaign::KMETA_ConfirmationPageText => $ConfirmationPageText
|
||||
)
|
||||
IperCptCampaign::kMETA_WEB_PROMOTION_TEXT => $WebPromotionText,
|
||||
)
|
||||
);
|
||||
|
||||
wp_update_post($my_post);
|
||||
@@ -375,17 +281,13 @@ if(!class_exists('IperCampaignController')){
|
||||
IperCptCampaign::kMETA_CAMPAIGN_ID => $CampaignID,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_START_DATE => $StartDate,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_PHONE => $PhoneNumber,
|
||||
IperCptCampaign::KMETA_CanaryPhone => $CanaryPhone,//pull text from sales force
|
||||
IperCptCampaign::KMETA_ControlPhone => $ControlPhone,//pull text from sales force
|
||||
IperCptCampaign::kMETA_CAMPAIGN_LANDING_URL => $LandingURL,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_SHORT_URL => $FriendlyURL,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_END_DATE => $EndDate,
|
||||
IperCptCampaign::kMETA_CAMPAIGN_NAME => $CampaignName,
|
||||
IperCptCampaign::kMETA_FIVE9 => $Five9CallbackCampaign,
|
||||
IperCptCampaign::kMETA_WEB_PROMOTION_TEXT => $WebPromotionText,//pull text from sales force
|
||||
IperCptCampaign::KMETA_AB_Test => $ABTest,//pull text from sales force
|
||||
IperCptCampaign::KMETA_WEB_TOP_BAR => $WebTopBarSpecialOffer,//pull text from sales force
|
||||
IperCptCampaign::KMETA_ConfirmationPageText => $ConfirmationPageText//pull text from sales force
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: fabrizio pera
|
||||
* Date: 22/11/16
|
||||
* Time: 10:52
|
||||
*/
|
||||
|
||||
if(!class_exists('IperCptCampaign')) {
|
||||
|
||||
@@ -17,48 +11,36 @@ if(!class_exists('IperCptCampaign')) {
|
||||
const DESCRIPTION = "Post type for Campaign";
|
||||
const QUERY_VAR = "campaign";
|
||||
|
||||
//meta key
|
||||
|
||||
const kMETA_CAMPAIGN_ID = "campaign_id";
|
||||
const kMETA_CAMPAIGN_START_DATE = "campaign_start_date";
|
||||
const kMETA_CAMPAIGN_END_DATE = "campaign_end_date";
|
||||
const kMETA_CAMPAIGN_PHONE = "campaign_phone_number";
|
||||
const KMETA_ControlPhone = "ControlPhoneNumber";
|
||||
const KMETA_CanaryPhone = "CanaryPhoneNumber";
|
||||
const kMETA_CAMPAIGN_SHORT_URL = "campaign_short_url";
|
||||
const kMETA_CAMPAIGN_LANDING_URL = "campaign_landing_url";
|
||||
const kMETA_CAMPAIGN_NAME = "campaign_name";
|
||||
const kMETA_DELETE = "to_delete";
|
||||
const kMETA_FIVE9 = "Five9CallbackCampaign";
|
||||
const kMETA_WEB_PROMOTION_TEXT = "WebPromotionText";//Name text for campaign field
|
||||
const KMETA_WEB_TOP_BAR = "WebTopBarSpecialOffer";
|
||||
const KMETA_Google_KW = "GoogleKW";
|
||||
const KMETA_AB_Test = "ABTest";
|
||||
const KMETA_ConfirmationPageText = "ConfirmationPageText";
|
||||
|
||||
|
||||
|
||||
//meta array
|
||||
|
||||
private $_meta = array(
|
||||
array('name'=>self::kMETA_CAMPAIGN_ID,'type'=>'input-text','title'=>'Campaign ID'),
|
||||
array('name'=>self::kMETA_CAMPAIGN_NAME,'type'=>'input-text','title'=>'Campaign name'),
|
||||
array('name'=>self::kMETA_CAMPAIGN_START_DATE,'type'=>'input-date','title'=>'Start date'),
|
||||
array('name'=>self::kMETA_CAMPAIGN_END_DATE,'type'=>'input-date','title'=>'End date'),
|
||||
array('name'=>self::kMETA_CAMPAIGN_PHONE,'type'=>'input-text','title'=>'Phone number'),
|
||||
array('name'=>self::KMETA_ControlPhone,'type'=>'input-text','title'=>'Control Phone number'),
|
||||
array('name'=>self::KMETA_CanaryPhone,'type'=>'input-text','title'=>'Canary 800 Number'),
|
||||
array('name'=>self::kMETA_CAMPAIGN_SHORT_URL,'type'=>'input-text','title'=>'Friendly URL'),
|
||||
array('name'=>self::kMETA_CAMPAIGN_LANDING_URL,'type'=>'input-text','title'=>'Landing URL'),
|
||||
array('name'=>self::kMETA_FIVE9,'type'=>'input-text','title'=>'Five9 Callback Campaign'),
|
||||
array('name'=>self::kMETA_WEB_PROMOTION_TEXT,'type'=>'input-text','title'=>'Web Promotion Text'),//label name for campaign field
|
||||
array('name'=>self::KMETA_WEB_TOP_BAR,'type'=>'input-text','title'=>'Web Top Bar Special Offer'),
|
||||
array('name'=>self::KMETA_Google_KW,'type'=>'input-text','title'=>'Google KW'),
|
||||
array('name'=>self::KMETA_AB_Test,'type'=>'input-text','title'=>'A/B Test'),
|
||||
array('name'=>self::KMETA_ConfirmationPageText,'type'=>'input-text','title'=>'Confirmation Page Text')
|
||||
array('name'=>self::kMETA_WEB_PROMOTION_TEXT,'type'=>'input-text','title'=>'Web Promotion Text'),
|
||||
);
|
||||
|
||||
public function __construct(){
|
||||
add_action('init', array(&$this, 'init'));
|
||||
add_action('admin_init', array(&$this, 'admin_init'));
|
||||
//add_action('admin_print_scripts', array(&$this,'load_custom_wp_admin_script') );
|
||||
|
||||
add_filter('single_template',array(&$this,'single_template'));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,11 @@ $campaignTitle = get_the_title();
|
||||
|
||||
$campaignID = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_CAMPAIGN_ID,true);
|
||||
$campaignPhone = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_CAMPAIGN_PHONE,true);
|
||||
$controlPhone = get_post_meta(get_the_ID(),IperCptCampaign::KMETA_ControlPhone,true);
|
||||
$CanaryPhone = get_post_meta(get_the_ID(),IperCptCampaign::KMETA_CanaryPhone,true);
|
||||
$campaignStart = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_CAMPAIGN_START_DATE,true);
|
||||
$campaignEnd = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_CAMPAIGN_END_DATE,true);
|
||||
$campaignLink = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_CAMPAIGN_LANDING_URL,true);
|
||||
$campaignFive9CallbackCampaign = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_FIVE9,true);
|
||||
$WebPromotionText = get_post_meta(get_the_ID(),IperCptCampaign::kMETA_WEB_PROMOTION_TEXT,true);
|
||||
$WebTopBarSpecialOffer = get_post_meta(get_the_ID(),IperCptCampaign::KMETA_WEB_TOP_BAR,true);
|
||||
$Google_KW = get_post_meta(get_the_ID(),IperCptCampaign::KMETA_Google_KW,true);
|
||||
$ABTest = get_post_meta(get_the_ID(),IperCptCampaign::KMETA_AB_Test,true);
|
||||
$ConfirmationPageText = get_post_meta(get_the_ID(),IperCptCampaign::KMETA_ConfirmationPageText,true);
|
||||
|
||||
$campaignStart.=" 00:00:00";
|
||||
$campaignEnd.=" 23:59:59";
|
||||
@@ -25,10 +19,8 @@ $campaignStart = strtotime($campaignStart);
|
||||
$campaignEnd = strtotime($campaignEnd);
|
||||
|
||||
if($now>=$campaignStart && $now<=$campaignEnd){
|
||||
|
||||
//campaign active
|
||||
$controller = IperCampaignController::instance();
|
||||
$controller->setCampaign($campaignID,$campaignPhone,$campaignFive9CallbackCampaign,$WebPromotionText,$WebTopBarSpecialOffer,$Google_KW,$ABTest,$ConfirmationPageText,$CanaryPhone,$controlPhone);
|
||||
$controller->setCampaign($campaignID,$campaignPhone,$campaignFive9CallbackCampaign,$WebPromotionText);
|
||||
|
||||
}else{
|
||||
//campaign expired or not yet started
|
||||
@@ -43,12 +35,6 @@ $myurl = get_option('siteurl');
|
||||
$campaignurl = (empty($campaignLink)) ? get_home_url() : $campaignLink;
|
||||
|
||||
$utm_campaign = $_GET['dynamic_id'];
|
||||
/* For testing
|
||||
ob_flush();
|
||||
ob_start();
|
||||
var_dump($permalink);
|
||||
file_put_contents("dumps.txt", ob_get_flush());
|
||||
*/
|
||||
|
||||
switch ($utm_campaign) {
|
||||
case "landline" :
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('wp-components', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins', 'wp-polyfill'), 'version' => 'b81b50e9375d8f85569a43863b885812');
|
||||
832
wp/wp-content/plugins/relevanssi-premium/build/index.js
Normal file
832
wp/wp-content/plugins/relevanssi-premium/build/index.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1576
wp/wp-content/plugins/relevanssi-premium/changelog.txt
Normal file
1576
wp/wp-content/plugins/relevanssi-premium/changelog.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:05+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;","lang":"cs_CZ"},"Insights":["P\u0159ehledy"]}},"comment":{"reference":"index.js"}}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:04+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n != 1;","lang":"de"},"Ignore post content in the indexing.":["Beitragsinhalt in der Indexierung ignorieren."],"Low-ranking search terms used to find this post:":["Niedrig rankende Suchbegriffe, um diesen Beitrag zu finden:"],"The most common search terms used to find this post:":["Die h\u00e4ufigsten Suchbegriffe, um diesen Beitrag zu finden:"],"Excluded posts for this post:":["Ausgeschlossene Beitr\u00e4ge f\u00fcr diesen Beitrag:"],"Related posts for this post:":["Verwandte Beitr\u00e4ge f\u00fcr diesen Beitrag:"],"Related posts":["Verwandte Beitr\u00e4ge"],"Exclusion":["Ausschluss"],"Pinning":["Anheften"],"Reason this post is not indexed:":["Grund, warum dieser Beitrag nicht indexiert ist:"],"MySQL columns:":["MySQL-Spalten:"],"Links to this post:":["Link zu diesem Beitrag:"],"Excerpt:":["Textauszug:"],"Custom fields:":["Individuelle Felder:"],"Comments:":["Kommentare:"],"Other taxonomies:":["Andere Taxonomien:"],"Tags:":["Schlagw\u00f6rter:"],"Categories:":["Kategorien:"],"Author:":["Autor:"],"Content:":["Inhalt:"],"Title:":["Titel:"],"use this":["dieses benutzen"],"not this":["nicht dieses"],"Insights":["Einsichten"],"A comma-separated list of post IDs to use as related posts for this post":["Eine kommagetrennte Liste von Beitrags-IDs, die als verwandte Beitr\u00e4ge f\u00fcr diesen Beitrag verwendet werden sollen"],"Don't show this as a related post for any post.":["Dies nicht als verwandten Beitrag f\u00fcr einen Beitrag anzeigen."],"Don't append the related posts to this page.":["Die verwandten Beitr\u00e4ge nicht an diese Seite anh\u00e4ngen."],"Exclude this post or page from the index.":["Diesen Beitrag oder diese Seite aus dem Index ausschlie\u00dfen."],"Pin this post for all searches it appears in.":["Diesen Beitrag f\u00fcr alle Suchanfragen anheften, in denen er erscheint."],"How Relevanssi sees this post":["Wie Relevanssi diesen Beitrag sieht"]}},"comment":{"reference":"index.js"}}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:05+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n != 1;","lang":"es"},"Ignore post content in the indexing.":["Ignora el contenido de la entrada en la indexaci\u00f3n."],"Low-ranking search terms used to find this post:":["T\u00e9rminos de b\u00fasqueda de bajo rango utilizados para encontrar esta entrada:"],"The most common search terms used to find this post:":["T\u00e9rminos de b\u00fasqueda m\u00e1s comunes utilizados para encontrar esta entrada:"],"Excluded posts for this post:":["Entradas excluidas para esta entrada:"],"Related posts for this post:":["Entradas relacionadas para esta entrada:"],"Related posts":["Entradas relacionadas"],"Exclusion":["Exclusi\u00f3n"],"Pinning":["Marcado"],"Reason this post is not indexed:":["Raz\u00f3n por la que esta entrada no est\u00e1 indexada:"],"MySQL columns:":["Columnas de MySQL"],"Links to this post:":["Enlaces a esta entrada:"],"Excerpt:":["Extracto:"],"Custom fields:":["Campos personalizados:"],"Comments:":["Comentarios:"],"Other taxonomies:":["Otras taxonom\u00edas:"],"Tags:":["Etiquetas:"],"Categories:":["Categor\u00edas:"],"Author:":["Autor:"],"Content:":["Contenido:"],"Title:":["T\u00edtulo:"],"use this":["usar este"],"not this":["no \u00e9ste"],"Insights":["Insights"],"A comma-separated list of post IDs to use as related posts for this post":["Lista separada por comas de ID de entradas para utilizarlas como entradas relacionadas de esta entrada"],"Don't show this as a related post for any post.":["No mostrar \u00e9ste como entrada relacionada de ninguna entradas."],"Don't append the related posts to this page.":["No a\u00f1adir entradas relacionadas a esta p\u00e1gina."],"Exclude this post or page from the index.":["Excluir esta entrada o p\u00e1gina del \u00edndex."],"Pin this post for all searches it appears in.":["Marca esta entrada para todas las b\u00fasquedas en las que aparezca."],"How Relevanssi sees this post":["C\u00f3mo ve Relevanssi esta entrada"]}},"comment":{"reference":"index.js"}}
|
||||
@@ -0,0 +1,120 @@
|
||||
{
|
||||
"translation-revision-date": "",
|
||||
"generator": "WP-CLI\/2.6.0",
|
||||
"source": "index.js",
|
||||
"domain": "messages",
|
||||
"locale_data": {
|
||||
"messages": {
|
||||
"": {
|
||||
"domain": "messages",
|
||||
"lang": "fi",
|
||||
"plural-forms": "nplurals=2; plural=(n != 1);"
|
||||
},
|
||||
"not this": [
|
||||
"ei t\u00e4t\u00e4"
|
||||
],
|
||||
"use this": [
|
||||
"k\u00e4yt\u00e4 t\u00e4t\u00e4"
|
||||
],
|
||||
"How Relevanssi sees this post": [
|
||||
"Kuinka Relevanssi n\u00e4kee artikkelin"
|
||||
],
|
||||
"Title:": [
|
||||
"Otsikko:"
|
||||
],
|
||||
"Content:": [
|
||||
"Sis\u00e4lt\u00f6:"
|
||||
],
|
||||
"Author:": [
|
||||
"Tekij\u00e4:"
|
||||
],
|
||||
"Categories:": [
|
||||
"Aiheet:"
|
||||
],
|
||||
"Tags:": [
|
||||
"Avainsanat:"
|
||||
],
|
||||
"Other taxonomies:": [
|
||||
"Muut taksonomiat:"
|
||||
],
|
||||
"Comments:": [
|
||||
"Kommentit:"
|
||||
],
|
||||
"Custom fields:": [
|
||||
"Avainkent\u00e4t:"
|
||||
],
|
||||
"Excerpt:": [
|
||||
"Ote:"
|
||||
],
|
||||
"Links to this post:": [
|
||||
"Sis\u00e4iset linkit:"
|
||||
],
|
||||
"MySQL columns:": [
|
||||
"MySQL-sarakkeet:"
|
||||
],
|
||||
"Reason this post is not indexed:": [
|
||||
"Miksi t\u00e4t\u00e4 artikkelia ei ole indeksoitu:"
|
||||
],
|
||||
"Pinning": [
|
||||
"Artikkelin kiinnitt\u00e4minen"
|
||||
],
|
||||
"Pin this post for all searches it appears in.": [
|
||||
"Kiinnit\u00e4 t\u00e4m\u00e4 artikkeli k\u00e4rkeen kaikissa hauissa, joissa se esiintyy."
|
||||
],
|
||||
"A comma-separated list of single word keywords or multi-word phrases.": [
|
||||
"Pilkuilla erotettu lista yksitt\u00e4isi\u00e4 hakusanoja tai monisanaisia hakulauseita."
|
||||
],
|
||||
"If any of these keywords are present in the search query, this post will be moved on top of the search results.": [
|
||||
"Jos joku n\u00e4ist\u00e4 hakusanoista esiintyy k\u00e4ytt\u00e4j\u00e4n haussa, t\u00e4m\u00e4 artikkeli kiinnitet\u00e4\u00e4n hakutulosten huipulle."
|
||||
],
|
||||
"You can add weights to pinned keywords like this: 'keyword (100)'. The post with the highest weight will be sorted first if there are multiple posts pinned to the same keyword.": [
|
||||
"Voit lis\u00e4t\u00e4 kiinnitetyille avainsanoille painoja n\u00e4in: \u2019avainsana (100)\u2019. Jos samalla avainsanalla on kiinnitetty useampi artikkeli, tuloslistan ensimm\u00e4iseksi nostetaan se, jonka paino on suurin."
|
||||
],
|
||||
"Exclusion": [
|
||||
"Artikkelien poissulkeminen"
|
||||
],
|
||||
"Exclude this post or page from the index.": [
|
||||
"Poista t\u00e4m\u00e4 artikkeli indeksist\u00e4."
|
||||
],
|
||||
"Ignore post content in the indexing.": [
|
||||
"\u00c4l\u00e4 huomioi artikkelin sis\u00e4lt\u00f6\u00e4 indeksoitaessa."
|
||||
],
|
||||
"If any of these keywords are present in the search query, this post will be removed from the search results.": [
|
||||
"Jos joku n\u00e4ist\u00e4 hakusanoista esiintyy k\u00e4ytt\u00e4j\u00e4n haussa, t\u00e4m\u00e4 artikkeli poistetaan hakutuloksista."
|
||||
],
|
||||
"Related posts": [
|
||||
"Aiheeseen liittyv\u00e4t artikkelit"
|
||||
],
|
||||
"Don't append the related posts to this page.": [
|
||||
"\u00c4l\u00e4 lis\u00e4\u00e4 samankaltaisia artikkeleita t\u00e4lle sivulle."
|
||||
],
|
||||
"Don't show this as a related post for any post.": [
|
||||
"\u00c4l\u00e4 n\u00e4yt\u00e4 t\u00e4t\u00e4 samankaltaisena artikkelina mill\u00e4\u00e4n sivulla."
|
||||
],
|
||||
"A comma-separated list of keywords to use for the Related Posts feature.": [
|
||||
"Pilkulla erotettu lista avainsanoja samankaltaisten artikkelien etsimiseen."
|
||||
],
|
||||
"Anything entered here will used when searching for related posts. Using phrases with quotes is allowed, but will restrict the related posts to posts including that phrase.": [
|
||||
"T\u00e4h\u00e4n merkittyj\u00e4 hakusanoja k\u00e4ytet\u00e4\u00e4n samankaltaisten artikkelien etsimiseen. Voit k\u00e4ytt\u00e4\u00e4 fraasihakua lainausmerkeill\u00e4, mutta se rajoittaa samankaltaiset artikkelit niihin, joissa fraasi esiintyy."
|
||||
],
|
||||
"A comma-separated list of post IDs to use as related posts for this post": [
|
||||
"Pilkuilla erotettu lista t\u00e4m\u00e4n artikkelin liittyvin\u00e4 artikkeleina k\u00e4ytett\u00e4vien artikkelien ID-numeroista"
|
||||
],
|
||||
"Related posts for this post:": [
|
||||
"Samankaltaiset artikkelit:"
|
||||
],
|
||||
"Excluded posts for this post:": [
|
||||
"\u00c4l\u00e4 k\u00e4yt\u00e4 samankaltaisina artikkeleina t\u00e4lle artikkelille:"
|
||||
],
|
||||
"Insights": [
|
||||
"Huomioita"
|
||||
],
|
||||
"The most common search terms used to find this post:": [
|
||||
"Yleisimm\u00e4t hakusanat, joilla t\u00e4m\u00e4 artikkeli l\u00f6ydet\u00e4\u00e4n:"
|
||||
],
|
||||
"Low-ranking search terms used to find this post:": [
|
||||
"Hakusanoja, joilla t\u00e4m\u00e4 artikkeli on l\u00f6ydetty matalilta sijoilta:"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
6886
wp/wp-content/plugins/relevanssi-premium/languages/relevanssi-fi.po
Normal file
6886
wp/wp-content/plugins/relevanssi-premium/languages/relevanssi-fi.po
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:04+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n > 1;","lang":"fr"},"Ignore post content in the indexing.":["Ignorer le contenu de la publication dans l\u2019indexation."],"use this":["utiliser ceci"],"not this":["pas cela"],"Insights":["Insights"],"A comma-separated list of post IDs to use as related posts for this post":["Une liste d\u2019ID de publications s\u00e9par\u00e9s par des virgules \u00e0 utiliser comme publications similaires pour cette publication"],"Don't show this as a related post for any post.":["N\u2019affichez ceci comme une publication similaire pour aucune publication."],"Don't append the related posts to this page.":["N\u2019ajoutez pas les publications similaires \u00e0 cette page."],"Exclude this post or page from the index.":["Exclure cette publication ou cette page de l\u2019index."],"Pin this post for all searches it appears in.":["\u00c9pinglez cette publication pour toutes les recherches dans lesquelles elle appara\u00eet."],"How Relevanssi sees this post":["Comment Relevanssi voit cette publication"]}},"comment":{"reference":"index.js"}}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:04+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n != 1;","lang":"it"},"Insights":["Approfondimenti (Insights)"]}},"comment":{"reference":"index.js"}}
|
||||
Binary file not shown.
@@ -0,0 +1,321 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Relevanssi\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-08-14 14:06+0200\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Alessandro Fiorotto <alex@fiorotto.com>\n"
|
||||
"Language-Team: Fiorotto <alex@fiorotto.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-Language: Italian\n"
|
||||
"X-Poedit-Country: ITALY\n"
|
||||
"X-Poedit-SourceCharset: utf-8\n"
|
||||
|
||||
#: relevanssi.php:703
|
||||
msgid "There is no excerpt because this is a protected post."
|
||||
msgstr "Non c'è alcun estratto perché il post è protetto."
|
||||
|
||||
#: relevanssi.php:994
|
||||
msgid "Indexing complete!"
|
||||
msgstr "Indicizzazione completata!"
|
||||
|
||||
#: relevanssi.php:1183
|
||||
msgid "Relevanssi Search Options"
|
||||
msgstr "Opzioni per Relevanssi Search"
|
||||
|
||||
#: relevanssi.php:1294
|
||||
#, php-format
|
||||
msgid "<div id='message' class='update fade'><p>Term '%s' added to stopwords!</p></div>"
|
||||
msgstr "<div id='message' class='update fade'><p>Termine '%s' aggiunto alle parole inutili ai fini della ricerca!</p></div>"
|
||||
|
||||
#: relevanssi.php:1297
|
||||
#, php-format
|
||||
msgid "<div id='message' class='update fade'><p>Couldn't add term '%s' to stopwords!</p></div>"
|
||||
msgstr "<div id='message' class='update fade'><p>Non posso aggiungere il termine '%s' alle parole inutili ai fini della ricerca!</p></div>"
|
||||
|
||||
#: relevanssi.php:1306
|
||||
msgid "25 most common words in the index"
|
||||
msgstr "Le 25 parole più comuni nell'indice"
|
||||
|
||||
#: relevanssi.php:1308
|
||||
msgid "These words are excellent stopword material. A word that appears in most of the posts in the database is quite pointless when searching. This is also an easy way to create a completely new stopword list, if one isn't available in your language. Click the icon after the word to add the word to the stopword list. The word will also be removed from the index, so rebuilding the index is not necessary."
|
||||
msgstr "Queste parole possono dimostrarsi inutili ai fini della ricerca. Una parola che compare nella maggior parte dei posti nel database è piuttosto inutile ai fini di una buona ricerca. Questo è anche un modo semplice per creare un nuovo elenco di parole non significative, se non è disponibile nella tua lingua. Fare clic sull'icona dopo la parola per aggiungere la parola alla lista delle parole non significative. La parola sarà rimossa dall'indice e non sarà necessario ricostruire l'indice se si effettua una modifica."
|
||||
|
||||
#: relevanssi.php:1331
|
||||
msgid "Add to stopwords"
|
||||
msgstr "Aggiungi alle parole inutili ai fini della ricerca"
|
||||
|
||||
#: relevanssi.php:1344
|
||||
msgid "25 most popular queries"
|
||||
msgstr "25 ricerche più effettuate"
|
||||
|
||||
#: relevanssi.php:1356
|
||||
msgid "Recent queries that got 0 hits"
|
||||
msgstr "Recenti ricerche che non hanno dato risultati"
|
||||
|
||||
#: relevanssi.php:1491
|
||||
msgid "Title boost:"
|
||||
msgstr "Potenziamento dal titolo:"
|
||||
|
||||
#: relevanssi.php:1492
|
||||
#, php-format
|
||||
msgid "Default: %d. 0 means titles are ignored, 1 means no boost, more than 1 gives extra value."
|
||||
msgstr "Predefinito %d. 0 significa che i titoli sono ignorati, 1 significa non aumentare, mentre più di 1 da un valore in più."
|
||||
|
||||
#: relevanssi.php:1493
|
||||
msgid "Tag boost:"
|
||||
msgstr "Potenziamento da TAG"
|
||||
|
||||
#: relevanssi.php:1494
|
||||
#, php-format
|
||||
msgid "Default: %d. 0 means tags are ignored, 1 means no boost, more than 1 gives extra value."
|
||||
msgstr "Predefinito %d. 0 significa che i tag sono ignorati, 1 significa non aumentare, mentre più di 1 da un valore in più."
|
||||
|
||||
#: relevanssi.php:1495
|
||||
msgid "Comment boost:"
|
||||
msgstr "Potenziamento dai commenti:"
|
||||
|
||||
#: relevanssi.php:1496
|
||||
#, php-format
|
||||
msgid "Default: %d. 0 means comments are ignored, 1 means no boost, more than 1 gives extra value."
|
||||
msgstr "Predefinito %d. 0 significa che i commenti sono ignorati, 1 significa non aumentare, mentre più di 1 da un valore in più."
|
||||
|
||||
#: relevanssi.php:1497
|
||||
msgid "Use search for admin:"
|
||||
msgstr "Usa ricerca per admin:"
|
||||
|
||||
#: relevanssi.php:1498
|
||||
msgid "If checked, Relevanssi will be used for searches in the admin interface"
|
||||
msgstr "Se selezionato, Relevanssi sarà usato anche per le ricerche nell'interfaccia di amministrazione"
|
||||
|
||||
#: relevanssi.php:1499
|
||||
msgid "Restrict search to these categories and tags:"
|
||||
msgstr "Circoscrivi la ricerca a queste categorie e tag:"
|
||||
|
||||
#: relevanssi.php:1500
|
||||
msgid "Enter a comma-separated list of category and tag IDs to restrict search to those categories or tags. You can also use <code><input type='hidden' name='cat' value='list of cats and tags' /></code> in your search form. The input field will overrun this setting."
|
||||
msgstr "Inserire un elenco separato da virgola, con gli id degli articoli e/o delle pagine a cui sarà circoscritto l'ambito di ricerca. Si può anche usare il codice <code><input type='hidden' name='cat' value='list of cats and tags' /></code> nel modulo di ricerca e quello che si inserirà nel modulo sovrascriverà quanto impostato qui."
|
||||
|
||||
#: relevanssi.php:1501
|
||||
msgid "Exclude these categories and tags from search:"
|
||||
msgstr "Escludi queste categorie e tag dalla ricerca:"
|
||||
|
||||
#: relevanssi.php:1502
|
||||
msgid "Enter a comma-separated list of category and tag IDs that are excluded from search results. This only works here, you can't use the input field option (WordPress doesn't pass custom parameters there)."
|
||||
msgstr "Inserire un elenco separato da virgola, con gli id delle categorie e dei tag esclusi dai risultati della ricerca. Non è possibile sovrascrivere o cambiare questa impostazione inserendo dell'apposito codice nel modulo di ricerca."
|
||||
|
||||
#: relevanssi.php:1505
|
||||
msgid "Exclude these posts/pages from search:"
|
||||
msgstr "Escludi questi articoli/pagine dalla ricerca:"
|
||||
|
||||
#: relevanssi.php:1506
|
||||
msgid "Enter a comma-separated list of post/page IDs that are excluded from search results. This only works here, you can't use the input field option (WordPress doesn't pass custom parameters there)."
|
||||
msgstr "Inserire un elenco separato da virgola, con gli id degli articoli e/o delle pagine esclusi dai risultati della ricerca. Non è possibile sovrascrivere o cambiare questa impostazione inserendo dell'apposito codice nel modulo di ricerca."
|
||||
|
||||
#: relevanssi.php:1507
|
||||
msgid "Index and search your posts' tags:"
|
||||
msgstr "Indicizza e cerca i tag degli articoli:"
|
||||
|
||||
#: relevanssi.php:1508
|
||||
msgid "If checked, Relevanssi will also index and search the tags of your posts. Remember to rebuild the index if you change this option!"
|
||||
msgstr "Se selezionato, Relevanssi indicizzerà anche i tag degli articoli. Ricordati di ricostruire l'indice se cambi questa opzione!"
|
||||
|
||||
#: relevanssi.php:1509
|
||||
msgid "Index and search these comments:"
|
||||
msgstr "Indicizza e ricerca questi commenti:"
|
||||
|
||||
#: relevanssi.php:1510
|
||||
msgid "Relevanssi will index and search ALL (all comments including track- & pingbacks and custom comment types), NONE (no comments) or NORMAL (manually posted comments on your blog).<br />Remember to rebuild the index if you change this option!"
|
||||
msgstr "Relevanssi consente di indicizzare e di effettuare le ricerche su TUTTO (compresi tutti i commenti, track & pingbacks e i commenti personalizzati), NESSUNO (commenti esclusi) o NORMALE (solo i commenti inseriti manualmente nel tuo blog). <br /> Ricordati di ricostruire l'indice, se modifichi questa opzione!"
|
||||
|
||||
#: relevanssi.php:1511
|
||||
msgid "all"
|
||||
msgstr "tutto"
|
||||
|
||||
#: relevanssi.php:1512
|
||||
msgid "normal"
|
||||
msgstr "normale"
|
||||
|
||||
#: relevanssi.php:1513
|
||||
msgid "none"
|
||||
msgstr "nessuno"
|
||||
|
||||
#: relevanssi.php:1516
|
||||
msgid "Create custom search result snippets:"
|
||||
msgstr "Crea un frammento di ricerca personalizzato:"
|
||||
|
||||
#: relevanssi.php:1517
|
||||
msgid "If checked, Relevanssi will create excerpts that contain the search term hits. To make them work, make sure your search result template uses the_excerpt() to display post excerpts."
|
||||
msgstr "Se selezionato, Relevanssi creerà un estratto che conterrà la parola cercata. Affinché funzioni, assicurarsi che il template utilizzi la funzione the_excerpt() per visualizzare il risultato della ricerca."
|
||||
|
||||
#: relevanssi.php:1518
|
||||
msgid "Length of the snippet:"
|
||||
msgstr "Lunghezza del frammento:"
|
||||
|
||||
#: relevanssi.php:1519
|
||||
msgid "This must be an integer."
|
||||
msgstr "Deve essere un numero intero."
|
||||
|
||||
#: relevanssi.php:1520
|
||||
msgid "words"
|
||||
msgstr "parole"
|
||||
|
||||
#: relevanssi.php:1521
|
||||
msgid "characters"
|
||||
msgstr "caratteri"
|
||||
|
||||
#: relevanssi.php:1522
|
||||
msgid "Keep a log of user queries:"
|
||||
msgstr "Conserva un log delle ricerche:"
|
||||
|
||||
#: relevanssi.php:1523
|
||||
msgid "If checked, Relevanssi will log user queries."
|
||||
msgstr "Se selezionato, Relevanssi terrà traccia delle ricerche effettuate."
|
||||
|
||||
#: relevanssi.php:1524
|
||||
msgid "Highlight query terms in search results:"
|
||||
msgstr "Evidenzia i termini di ricerca nei risultati:"
|
||||
|
||||
#: relevanssi.php:1525
|
||||
msgid "Highlighting isn't available unless you use custom snippets"
|
||||
msgstr "L'evidenziazione non è disponibile se non si utilizzano degli snippet personalizzati"
|
||||
|
||||
#: relevanssi.php:1526
|
||||
msgid "Highlight query terms in result titles too:"
|
||||
msgstr "Evidenzia i termini di ricerca anche nei titoli dei risultati:"
|
||||
|
||||
#: relevanssi.php:1529
|
||||
msgid "Save"
|
||||
msgstr "Salva"
|
||||
|
||||
#: relevanssi.php:1530
|
||||
msgid "Building the index and indexing options"
|
||||
msgstr "Costruisci l'indice e salva le opzioni di indicizzazione"
|
||||
|
||||
#: relevanssi.php:1531
|
||||
msgid "After installing the plugin, you need to build the index. This generally needs to be done once, you don't have to re-index unless something goes wrong. Indexing is a heavy task and might take more time than your servers allow. If the indexing cannot be finished - for example you get a blank screen or something like that after indexing - you can continue indexing from where you left by clicking 'Continue indexing'. Clicking 'Build the index' will delete the old index, so you can't use that."
|
||||
msgstr "Dopo aver installato il plugin, è necessario costruire l'indice. Questo genere deve essere fatto una volta solo e non si deve reindicizzare fino a che qualcosa non funziona bene. L'indicizzazione è un compito pesante e potrebbe richiedere più tempo di quanto i server consentono. Se l'indicizzazione non viene completata e si ottine ad esempio una pagina bianca o qualcosa del genere, è possibile continuare l'indicizzazione dal punto in cui è stata interrotta semplicemente premendo il tasto 'Continua indicizzazione'. Cliccando invece su 'costruisci l'indice' si reinizierà da zero la creazione dell'indicie."
|
||||
|
||||
#: relevanssi.php:1532
|
||||
msgid "So, if you build the index and don't get the 'Indexing complete' in the end, keep on clicking the 'Continue indexing' button until you do. On my blogs, I was able to index ~400 pages on one go, but had to continue indexing twice to index ~950 pages."
|
||||
msgstr "Se si crea l'indice e alla fine non si ottiene il risultato di 'indicizzazione completa', cliccare nuovamente sul pulsante 'Continua indicizzazione' fino a quando non si otterrà tale risultato. Il mo blog ad esempio è stato in grado di indicizzare circa 400 pagine in una volta sola, ma ha dovuto continuare l'indicizzazione due volte per completare l'indice di circa 950 pagine."
|
||||
|
||||
#: relevanssi.php:1533
|
||||
msgid "Save indexing options and build the index"
|
||||
msgstr "Salva le opzioni di indicizzazione e costruisci l'indice"
|
||||
|
||||
#: relevanssi.php:1534
|
||||
msgid "Continue indexing"
|
||||
msgstr "Continua indicizzazione"
|
||||
|
||||
#: relevanssi.php:1535
|
||||
msgid "No highlighting"
|
||||
msgstr "No evidenziazione"
|
||||
|
||||
#: relevanssi.php:1536
|
||||
msgid "Text color"
|
||||
msgstr "Colore del testo"
|
||||
|
||||
#: relevanssi.php:1537
|
||||
msgid "Background color"
|
||||
msgstr "Colore di sfondo"
|
||||
|
||||
#: relevanssi.php:1538
|
||||
msgid "CSS Style"
|
||||
msgstr "Stile CSS"
|
||||
|
||||
#: relevanssi.php:1539
|
||||
msgid "CSS Class"
|
||||
msgstr "Classe CSS"
|
||||
|
||||
#: relevanssi.php:1541
|
||||
msgid "Text color for highlights:"
|
||||
msgstr "Colore del testo delle evidenziazioni:"
|
||||
|
||||
#: relevanssi.php:1542
|
||||
msgid "Background color for highlights:"
|
||||
msgstr "Colore di sfondo delle evidenziazioni:"
|
||||
|
||||
#: relevanssi.php:1543
|
||||
msgid "CSS style for highlights:"
|
||||
msgstr "Stile CSS per le evidenziazioni:"
|
||||
|
||||
#: relevanssi.php:1544
|
||||
msgid "CSS class for highlights:"
|
||||
msgstr "Classe CSS per le evidenziazioni:"
|
||||
|
||||
#: relevanssi.php:1546
|
||||
#: relevanssi.php:1547
|
||||
msgid "Use HTML color codes (#rgb or #rrggbb)"
|
||||
msgstr "Usare il codice colore HTML (#rgb o #rrggbb)"
|
||||
|
||||
#: relevanssi.php:1548
|
||||
msgid "You can use any CSS styling here, style will be inserted with a <span>"
|
||||
msgstr "È possibile usare qualsiasi stile CSS, lo stile sarà inserito con <span>"
|
||||
|
||||
#: relevanssi.php:1549
|
||||
msgid "Name a class here, search results will be wrapped in a <span> with the class"
|
||||
msgstr "Nome della classe qui. I risultati di ricerca saranno compresi in <span> con la classe"
|
||||
|
||||
#: relevanssi.php:1551
|
||||
msgid "What to include in the index"
|
||||
msgstr "Cosa includere nell'indice"
|
||||
|
||||
#: relevanssi.php:1552
|
||||
msgid "Everything"
|
||||
msgstr "Ogni cosa"
|
||||
|
||||
#: relevanssi.php:1553
|
||||
msgid "Just posts"
|
||||
msgstr "Solo articoli"
|
||||
|
||||
#: relevanssi.php:1554
|
||||
msgid "Just pages"
|
||||
msgstr "Solo pagine"
|
||||
|
||||
#: relevanssi.php:1556
|
||||
msgid "Custom fields to index:"
|
||||
msgstr "Campi personalizzati da indicizzare:"
|
||||
|
||||
#: relevanssi.php:1557
|
||||
msgid "A comma-separated list of custom field names to include in the index."
|
||||
msgstr "Una lista separata da virgola dei nomi personalizzati da includere nell'indice."
|
||||
|
||||
#: relevanssi.php:1559
|
||||
msgid "Show breakdown of search hits in excerpts:"
|
||||
msgstr "Viusalizza un separatore nei risultati di ricerca:"
|
||||
|
||||
#: relevanssi.php:1560
|
||||
msgid "Check this to show more information on where the search hits were made. Requires custom snippets to work."
|
||||
msgstr "Seleziona qui per mostrare più informazioni o per definire dove sarà effettuata la ricerca. Per attivarlo richiede uno snippet personalizzato."
|
||||
|
||||
#: relevanssi.php:1561
|
||||
msgid "The breakdown format:"
|
||||
msgstr "Formato dell'interruzione:"
|
||||
|
||||
#: relevanssi.php:1562
|
||||
msgid "Use %body%, %title%, %tags%, %comments% and %score% to display the number of hits and the document weight."
|
||||
msgstr "Usa %body%, %title%, %tags%, %comments% e %score% per visualizzare il numero di ricorrenze e il peso del documento."
|
||||
|
||||
#: relevanssi.php:1564
|
||||
msgid "When to use fuzzy matching?"
|
||||
msgstr "Quando usare la ricerca per parola simile?"
|
||||
|
||||
#: relevanssi.php:1565
|
||||
msgid "When straight search gets no hits"
|
||||
msgstr "Quando la ricerca regolare non produce risultati"
|
||||
|
||||
#: relevanssi.php:1566
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
|
||||
#: relevanssi.php:1567
|
||||
msgid "Don't use fuzzy search"
|
||||
msgstr "Non usare la ricerca per similitudini"
|
||||
|
||||
#: relevanssi.php:1568
|
||||
msgid "Straight search matches just the term. Fuzzy search matches everything that begins or ends with the search term."
|
||||
msgstr "La ricerca regolare cerca semplicemente un termine. La ricerca per similitudine trova anche tutti i termini che iniziano o finiscono come il termine di ricerca."
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-01-25 12:26:59+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=1; plural=0;","lang":"ja_JP"},"Insights":["Insights"]}},"comment":{"reference":"index.js"}}
|
||||
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:04+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n != 1;","lang":"nl"},"Insights":["Inzichten"]}},"comment":{"reference":"index.js"}}
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-02-21 15:40:15+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=(n > 1);","lang":"pt_BR"},"Insights":["Insights"]}},"comment":{"reference":"index.js"}}
|
||||
Binary file not shown.
@@ -0,0 +1,578 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Relevanssi\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Pedro Padron <ppadron@w3p.com.br>\n"
|
||||
"Language-Team: W3P Projetos Web <contato@w3p.com.br>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Poedit-Language: Portuguese\n"
|
||||
"X-Poedit-Country: BRAZIL\n"
|
||||
"X-Poedit-Basepath: /\n"
|
||||
"X-Poedit-SearchPath-0: /home/ppadron/Projects/wordpress-vanilla/wp-content/plugins/relevanssi\n"
|
||||
|
||||
#: relevanssi.php:1032
|
||||
msgid "There is no excerpt because this is a protected post."
|
||||
msgstr "Não há resumo porque esse é um post protegido."
|
||||
|
||||
#: relevanssi.php:1746
|
||||
msgid "Relevanssi Search Options"
|
||||
msgstr "Opções de Busca do Relevanssi"
|
||||
|
||||
#: relevanssi.php:1915
|
||||
msgid "25 most common words in the index"
|
||||
msgstr "25 palavras mais comuns no índice"
|
||||
|
||||
#: relevanssi.php:1917
|
||||
msgid "These words are excellent stopword material. A word that appears in most of the posts in the database is quite pointless when searching. This is also an easy way to create a completely new stopword list, if one isn't available in your language. Click the icon after the word to add the word to the stopword list. The word will also be removed from the index, so rebuilding the index is not necessary."
|
||||
msgstr "Estas palavras são excelentes para formar uma lista de stopwords. Uma palavra que aparece na maioria dos posts é um tanto quanto inútil em uma busca. Esta também é uma maneira fácil de criar uma nova lista de stopwords, caso uma não esteja disponível em seu idioma. Clique no ícone após a palavra para adicioná-la à lista de stopwords. A palavra também será removida do índice, então não é necessário reconstruí-lo."
|
||||
|
||||
#: relevanssi.php:1940
|
||||
msgid "Add to stopwords"
|
||||
msgstr "Adicionar à lista de stopwords"
|
||||
|
||||
#: relevanssi.php:1953
|
||||
msgid "25 most popular queries"
|
||||
msgstr "25 buscas mais populares"
|
||||
|
||||
#: relevanssi.php:1965
|
||||
msgid "Recent queries that got 0 hits"
|
||||
msgstr "Buscas recentes que não retornaram resultados"
|
||||
|
||||
#: relevanssi.php:2126
|
||||
msgid "Title boost:"
|
||||
msgstr "Prioridade do Título:"
|
||||
|
||||
#: relevanssi.php:2135
|
||||
msgid "Use search for admin:"
|
||||
msgstr "Usar a busca para o admin:"
|
||||
|
||||
#: relevanssi.php:2138
|
||||
msgid "Restrict search to these categories and tags:"
|
||||
msgstr "Restringir a busca para essas categorias e tags:"
|
||||
|
||||
#: relevanssi.php:2182
|
||||
msgid "Create custom search result snippets:"
|
||||
msgstr "Criar resumos de resultado de busca personalizados:"
|
||||
|
||||
#: relevanssi.php:2186
|
||||
msgid "Length of the snippet:"
|
||||
msgstr "Tamanho do resumo:"
|
||||
|
||||
#: relevanssi.php:2190
|
||||
msgid "Keep a log of user queries:"
|
||||
msgstr "Manter um histórico de buscas dos usuários:"
|
||||
|
||||
#: relevanssi.php:2191
|
||||
msgid "If checked, Relevanssi will log user queries."
|
||||
msgstr "Se ativada, Relevanssi irá armazenar as buscas feitas pelos usuários."
|
||||
|
||||
#: relevanssi.php:2195
|
||||
msgid "Highlight query terms in search results:"
|
||||
msgstr "Usar efeito marca-texto nos termos da busca nos resultados:"
|
||||
|
||||
#: relevanssi.php:2196
|
||||
msgid "Highlighting isn't available unless you use custom snippets"
|
||||
msgstr "Esta opção só está disponível se você utilizar resumos de resultados de busca personalizados"
|
||||
|
||||
#: relevanssi.php:2214
|
||||
msgid "Continue indexing"
|
||||
msgstr "Continuar Indexação"
|
||||
|
||||
#: relevanssi.php:2215
|
||||
msgid "No highlighting"
|
||||
msgstr "Sem efeito marca-texto"
|
||||
|
||||
#: relevanssi.php:2216
|
||||
msgid "Text color"
|
||||
msgstr "Cor do texto"
|
||||
|
||||
#: relevanssi.php:2217
|
||||
msgid "Background color"
|
||||
msgstr "Cor de fundo"
|
||||
|
||||
#: relevanssi.php:2218
|
||||
msgid "CSS Style"
|
||||
msgstr "CSS Style"
|
||||
|
||||
#: relevanssi.php:2219
|
||||
msgid "CSS Class"
|
||||
msgstr "Classe CSS"
|
||||
|
||||
#: relevanssi.php:2221
|
||||
msgid "Text color for highlights:"
|
||||
msgstr "Cor de texto para efeito marca-texto:"
|
||||
|
||||
#: relevanssi.php:2222
|
||||
msgid "Background color for highlights:"
|
||||
msgstr "Cor de fundo para efeito marca-texto:"
|
||||
|
||||
#: relevanssi.php:2223
|
||||
msgid "CSS style for highlights:"
|
||||
msgstr "Estilo CSS para efeito marca-texto:"
|
||||
|
||||
#: relevanssi.php:2224
|
||||
msgid "CSS class for highlights:"
|
||||
msgstr "Classe CSS para efeito marca-texto:"
|
||||
|
||||
#: relevanssi.php:2226
|
||||
#: relevanssi.php:2227
|
||||
msgid "Use HTML color codes (#rgb or #rrggbb)"
|
||||
msgstr "Use cores em hexadecimal (#rgb ou #rrggbb)"
|
||||
|
||||
# @ default
|
||||
#: relevanssi.php:94
|
||||
#, php-format
|
||||
msgid "Relevanssi needs attention: Remember to build the index (you can do it at <a href=\"%1$s\">the settings page</a>), otherwise searching won't work."
|
||||
msgstr "Relevanssi precisa de atenção: Lembre-se de construir o índice (você pode fazê-lo na <a href=\"%1$s\">página de opções</a>), caso contrário a busca não irá funcionar."
|
||||
|
||||
#: relevanssi.php:1430
|
||||
msgid "Indexing complete!"
|
||||
msgstr "Indexação concluída!"
|
||||
|
||||
#: relevanssi.php:1903
|
||||
#, php-format
|
||||
msgid "<div id='message' class='update fade'><p>Term '%s' added to stopwords!</p></div>"
|
||||
msgstr "<div id='message' class='update fade'><p>Termo '%s' adicionado à lista de stopwords!</p></div>"
|
||||
|
||||
#: relevanssi.php:1906
|
||||
#, php-format
|
||||
msgid "<div id='message' class='update fade'><p>Couldn't add term '%s' to stopwords!</p></div>"
|
||||
msgstr "<div id='message' class='update fade'><p>Não foi possível adicionar '%s' à lista de stopwords!</p></div>"
|
||||
|
||||
#: relevanssi.php:2129
|
||||
msgid "Tag boost:"
|
||||
msgstr "Prioridade da Tag:"
|
||||
|
||||
#: relevanssi.php:2132
|
||||
msgid "Comment boost:"
|
||||
msgstr "Prioridade dos Comentários:"
|
||||
|
||||
#: relevanssi.php:2143
|
||||
msgid "Exclude these categories and tags from search:"
|
||||
msgstr "Excluir da busca essas categorias e tags:"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2147
|
||||
msgid "Exclusions and restrictions"
|
||||
msgstr "Restrições"
|
||||
|
||||
#: relevanssi.php:2150
|
||||
msgid "Exclude these posts/pages from search:"
|
||||
msgstr "Excluir esses posts/páginas da busca:"
|
||||
|
||||
#: relevanssi.php:2154
|
||||
msgid "Index and search your posts' tags:"
|
||||
msgstr "Indexar e buscar as tags dos posts:"
|
||||
|
||||
#: relevanssi.php:2157
|
||||
msgid "Index and search these comments:"
|
||||
msgstr "Indexar e buscar nestes Comentários:"
|
||||
|
||||
#: relevanssi.php:2162
|
||||
msgid "all"
|
||||
msgstr "todos"
|
||||
|
||||
#: relevanssi.php:2163
|
||||
msgid "normal"
|
||||
msgstr "normal"
|
||||
|
||||
#: relevanssi.php:2164
|
||||
msgid "none"
|
||||
msgstr "nenhum"
|
||||
|
||||
#: relevanssi.php:2181
|
||||
msgid "Custom excerpts/snippets"
|
||||
msgstr "Resumos de resultado de busca personalizados"
|
||||
|
||||
#: relevanssi.php:2187
|
||||
msgid "This must be an integer."
|
||||
msgstr "O valor deve ser um número inteiro."
|
||||
|
||||
#: relevanssi.php:2188
|
||||
msgid "words"
|
||||
msgstr "palavras"
|
||||
|
||||
#: relevanssi.php:2189
|
||||
msgid "characters"
|
||||
msgstr "caracteres"
|
||||
|
||||
#: relevanssi.php:2192
|
||||
msgid "Search hit highlighting"
|
||||
msgstr "Efeito marca-texto"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2193
|
||||
msgid "First, choose the type of highlighting used:"
|
||||
msgstr "Primeiramente, escolha o tipo de efeito marca-texto a ser utilizado:"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2194
|
||||
msgid "Then adjust the settings for your chosen type:"
|
||||
msgstr "Ajuste as opções para o tipo escolhido:"
|
||||
|
||||
#: relevanssi.php:2198
|
||||
msgid "Highlight query terms in result titles too:"
|
||||
msgstr "Usar efeito marca-texto também nos títulos dos resultados:"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2201
|
||||
msgid "Save the options"
|
||||
msgstr "Gravar as opções"
|
||||
|
||||
#: relevanssi.php:2202
|
||||
msgid "Building the index and indexing options"
|
||||
msgstr "Construindo o índice e opções de indexação"
|
||||
|
||||
#: relevanssi.php:2213
|
||||
msgid "Save indexing options and build the index"
|
||||
msgstr "Gravar opções de indexação e construir o índice"
|
||||
|
||||
#: relevanssi.php:2233
|
||||
msgid "What to include in the index"
|
||||
msgstr "O que incluir no índice"
|
||||
|
||||
#: relevanssi.php:2234
|
||||
msgid "Everything"
|
||||
msgstr "Tudo"
|
||||
|
||||
#: relevanssi.php:2235
|
||||
msgid "Just posts"
|
||||
msgstr "Apenas posts"
|
||||
|
||||
#: relevanssi.php:2236
|
||||
msgid "Just pages"
|
||||
msgstr "Apenas páginas"
|
||||
|
||||
#: relevanssi.php:2251
|
||||
msgid "Custom fields to index:"
|
||||
msgstr "Campos personalizados a serem indexados:"
|
||||
|
||||
#: relevanssi.php:2259
|
||||
msgid "Show breakdown of search hits in excerpts:"
|
||||
msgstr "Exibir mais informações de hits no resumo:"
|
||||
|
||||
#: relevanssi.php:2262
|
||||
msgid "The breakdown format:"
|
||||
msgstr "Formato das informações:"
|
||||
|
||||
#: relevanssi.php:2267
|
||||
msgid "When to use fuzzy matching?"
|
||||
msgstr "Quando utilizar busca fuzzy"
|
||||
|
||||
#: relevanssi.php:2268
|
||||
msgid "When straight search gets no hits"
|
||||
msgstr "Quando a busca direta não encontra resultados"
|
||||
|
||||
#: relevanssi.php:2269
|
||||
msgid "Always"
|
||||
msgstr "Sempre"
|
||||
|
||||
#: relevanssi.php:2270
|
||||
msgid "Don't use fuzzy search"
|
||||
msgstr "Não utilizar busca fuzzy"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:311
|
||||
msgid "Data wiped clean, you can now delete the plugin."
|
||||
msgstr "Dados removidos! Você pode remover o plugin agora."
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2280
|
||||
msgid "Uninstall"
|
||||
msgstr "Desinstalar"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2284
|
||||
msgid "Remove plugin data"
|
||||
msgstr "Remover todos os dados do plugin"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2274
|
||||
msgid "Expand shortcodes in post content:"
|
||||
msgstr "Converter os shortcodes "
|
||||
|
||||
#: relevanssi.php:2167
|
||||
msgid "Index and search your posts' categories:"
|
||||
msgstr "Indexar e buscar as categorias dos posts:"
|
||||
|
||||
#: relevanssi.php:2243
|
||||
msgid "Custom post types to index"
|
||||
msgstr "Tipos de Posts (custom post types) a serem indexados"
|
||||
|
||||
#: relevanssi.php:2255
|
||||
msgid "Custom taxonomies to index:"
|
||||
msgstr "Taxonomias personalizadas a serem indexadas:"
|
||||
|
||||
#: relevanssi.php:2127
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Default: %d. 0 means titles are ignored, 1 means no boost, more\n"
|
||||
"\t\tthan 1 gives extra value."
|
||||
msgstr "Padrão: %d. 0 significa que os títulos são ignorados, 1 significa nenhuma prioridade, mais de 1 aumenta a prioridade."
|
||||
|
||||
#: relevanssi.php:2130
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Default: %d. 0 means tags are ignored, 1 means no boost, more\n"
|
||||
"\t\tthan 1 gives extra value."
|
||||
msgstr "Padrão: %d. 0 significa que as tags são ignoradas, 1 significa nenhuma prioridade, mais de 1 aumenta a prioridade."
|
||||
|
||||
#: relevanssi.php:2133
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Default: %d. 0 means comments are ignored, 1 means no boost,\n"
|
||||
"\t\tmore than 1 gives extra value."
|
||||
msgstr "Padrão: %d. 0 significa que os comentários são ignorados, 1 significa nenhuma prioridade, mais de 1 aumenta a prioridade."
|
||||
|
||||
#: relevanssi.php:2136
|
||||
msgid ""
|
||||
"If checked, Relevanssi will be used for searches in the admin\n"
|
||||
"\t\tinterface"
|
||||
msgstr "Se a opção estiver marcada, Relevanssi será usado nas buscas no painel do admin"
|
||||
|
||||
#: relevanssi.php:2139
|
||||
msgid ""
|
||||
"Enter a comma-separated list of category and tag IDs to restrict search to\n"
|
||||
"\t\tthose categories or tags. You can also use <code><input type='hidden' name='cat'\n"
|
||||
"\t\tvalue='list of cats and tags' /></code> in your search form. The input field will\n"
|
||||
"\t\toverrun this setting."
|
||||
msgstr "Insira uma lista separada por vírgulas de categorias e IDs de tags para restringir a busca apenas nelas. Você também pode usar <code><input type='hidden' name='cat' value='lista de categorias e tags' /></code> em seu formulário. O campo no formulário tem prioridade sobre esta opção no painel."
|
||||
|
||||
#: relevanssi.php:2144
|
||||
msgid ""
|
||||
"Enter a comma-separated list of category and tag IDs that are excluded from\n"
|
||||
"\t\tsearch results. This only works here, you can't use the input field option (WordPress\n"
|
||||
"\t\tdoesn't pass custom parameters there)."
|
||||
msgstr "Insira uma lista separada por vírgulas de categorias e IDs de tags que serão excluídos dos resultados da busca. Essa opção só pode ser definida aqui, você não pode usar um campo adicional no formulário (WordPress não passa parâmetros personalizados lá)."
|
||||
|
||||
#: relevanssi.php:2151
|
||||
msgid ""
|
||||
"Enter a comma-separated list of post/page IDs that are excluded from search\n"
|
||||
"\t\tresults. This only works here, you can't use the input field option (WordPress doesn't pass\n"
|
||||
"\t\tcustom parameters there)."
|
||||
msgstr "Insira uma lista separada por vírgulas de IDs de posts/páginas que serão excluídos dos resultados da busca. Essa opção só pode ser definida aqui, você não pode usar um campo adicional no formulário (WordPress não passa parâmetros personalizados lá)."
|
||||
|
||||
#: relevanssi.php:2155
|
||||
msgid ""
|
||||
"If checked, Relevanssi will also index and search the tags of your posts.\n"
|
||||
"\t\tRemember to rebuild the index if you change this option!"
|
||||
msgstr "Se esta opção estiver marcada, Relevanssi irá indexar e realizar buscas nas tags de seus posts. Lembre-se de reconstruir o índice se você mudar esta opção!"
|
||||
|
||||
#: relevanssi.php:2158
|
||||
msgid ""
|
||||
"Relevanssi will index and search ALL (all comments including track-\n"
|
||||
"\t\t& pingbacks and custom comment types), NONE (no comments) or NORMAL (manually posted\n"
|
||||
"\t\tcomments on your blog).<br />Remember to rebuild the index if you change this option!"
|
||||
msgstr "Relevanssi irá indexar e buscar em TODOS (comentários, trackbacks, pingbacks e tipos personalizados de comentários), NENHUM (nenhum comentário) ou NORMAL (comentários postados manualmente no blog).<br/> Lembre-se de reconstruir o índice se você mudar esta opção!"
|
||||
|
||||
#: relevanssi.php:2168
|
||||
msgid ""
|
||||
"If checked, Relevanssi will also index and search the categories of your\n"
|
||||
"\t\tposts. Category titles will pass through 'single_cat_title' filter. Remember to rebuild the\n"
|
||||
"\t\tindex if you change this option!"
|
||||
msgstr "Se esta opção estiver marcada, Relevanssi irá indexar e realizar buscas nas categorias de seus posts. Lembre-se de reconstruir o índice se você mudar esta opção!"
|
||||
|
||||
#: relevanssi.php:2183
|
||||
msgid ""
|
||||
"If checked, Relevanssi will create excerpts that contain the search term\n"
|
||||
"\t\thits. To make them work, make sure your search result template uses the_excerpt() to\n"
|
||||
"\t\tdisplay post excerpts."
|
||||
msgstr "Se esta opção estiver marcada, Relevanssi irá criar resumos que contém o(s) termo(s) buscado(s). Para que isso funcione, certifique-se de que seu template de resultado de busca utiliza <code>the_excerpt()</code> para exibir resumos de posts."
|
||||
|
||||
#: relevanssi.php:2203
|
||||
msgid ""
|
||||
"After installing the plugin, you need to build the index. This generally needs\n"
|
||||
"\t\tto be done once, you don't have to re-index unless something goes wrong. Indexing is a heavy\n"
|
||||
"\t\ttask and might take more time than your servers allow. If the indexing cannot be finished -\n"
|
||||
"\t\tfor example you get a blank screen or something like that after indexing - you can continue\n"
|
||||
"\t\tindexing from where you left by clicking 'Continue indexing'. Clicking 'Build the index'\n"
|
||||
"\t\twill delete the old index, so you can't use that."
|
||||
msgstr "Após a instalação do plugin, é preciso construir o índice. Isso normalmente precisa ser feito apenas uma vez. Não é necessário reconstruir o índice a não ser que algo de errado aconteça. A indexação é uma tarefa pesada e pode levar mais tempo do que seus servidores permitam. Se a indexação não puder ser concluída - por exemplo, você encontrar uma tela branca ou algo parecido após a indexação - você pode continuar o processo a partir de onde parou ao clicar em \"Continuar Indexação\". Ao clicar em \"Construir o Índice\" o índice atual será removido, portanto não clique nele para continuar uma indexação interrompida."
|
||||
|
||||
#: relevanssi.php:2209
|
||||
msgid ""
|
||||
"So, if you build the index and don't get the 'Indexing complete' in the end,\n"
|
||||
"\t\tkeep on clicking the 'Continue indexing' button until you do. On my blogs, I was able to\n"
|
||||
"\t\tindex ~400 pages on one go, but had to continue indexing twice to index ~950 pages."
|
||||
msgstr "Portanto, se você construir o índice e não receber a mensagem \"Indexação Concluída\" no final, continue clicando em \"Continuar Indexação\" até que isso aconteça. Em meus blogs consegui indexar cerca de 400 páginas de uma só vez, mas precisei continuar o processo mais duas vezes para chegar a cerca de 950 páginas."
|
||||
|
||||
#: relevanssi.php:2228
|
||||
msgid ""
|
||||
"You can use any CSS styling here, style will be inserted with a\n"
|
||||
"\t\t<span>"
|
||||
msgstr "Você pode usar qualquer estilo CSS aqui, ele será inserido com a tag <code><span></code>"
|
||||
|
||||
#: relevanssi.php:2230
|
||||
msgid ""
|
||||
"Name a class here, search results will be wrapped in a <span>\n"
|
||||
"\t\twith the class"
|
||||
msgstr "Insira aqui o nome da classe e os resultados da busca serão encapsulados por uma tag <code><span></code> com esta classe"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2237
|
||||
msgid "All public post types"
|
||||
msgstr "Todos os tipos de post públicos"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2238
|
||||
msgid ""
|
||||
"This determines which post types are included in the index. Choosing\n"
|
||||
"\t\t'everything' will include posts, pages and all custom post types. 'All public post types'\n"
|
||||
"\t\tincludes all registered post types that don't have the 'exclude_from_search' set to true.\n"
|
||||
"\t\tThis includes post, page, attachment, and possible custom types. 'All public types'\n"
|
||||
"\t\trequires at least WP 2.9, otherwise it's the same as 'everything'."
|
||||
msgstr "Isso determina quais tipos de posts serão indexados. Ao escolher \"Tudo\" serão incluídos todos os posts, páginas e posts personalizados. \"Todos os tipos de post públicos\" inclui todos os tipos de posts públicos que não possuam o atributo \"exclude_from_search\" definido como verdadeiro, o que inclui posts, páginas, anexos e possivelmente posts personalizados. A opção \"Todos os tipos de post públicos\" requer Wordpress 2.9 ou superior, caso contrário será o mesmo que \"Tudo\"."
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2244
|
||||
msgid ""
|
||||
"If you don't want to index all custom post types, list here the custom\n"
|
||||
"\t\tpost types you want to see indexed. List comma-separated post type names (as used in the\n"
|
||||
"\t\tdatabase). You can also use a hidden field in the search form to restrict the search to a\n"
|
||||
"\t\tcertain post type: <code><input type='hidden' name='post_type' value='comma-separated\n"
|
||||
"\t\tlist of post types' /></code>. If you choose 'All public post types' or 'Everything'\n"
|
||||
"\t\tabove, this option has no effect."
|
||||
msgstr "Se você não quiser indexar todos os tipos de post personalizados, liste aqui quais são os tipos que você quer indexar. Insira os nomes dos tipos de posts em uma lista separada por vírgula. Você pode também usar um campo hidden no formário de busca para restringir a busca em um determinado tipo de post: <code><input type='hidden' name='post_type' value='lista de tipos de posts' /></code>. Se na opção anterior você escolheu \"Todos os tipos de posts públicos\" ou \"Tudo\", essa opção não terá efeito."
|
||||
|
||||
#: relevanssi.php:2252
|
||||
msgid ""
|
||||
"A comma-separated list of custom field names to include in the\n"
|
||||
"\t\tindex."
|
||||
msgstr "Uma lista separada por vírgula de nomes de campos personalizados a serem incluídos no índice."
|
||||
|
||||
#: relevanssi.php:2256
|
||||
msgid ""
|
||||
"A comma-separated list of custom taxonomies to include in the\n"
|
||||
"\t\tindex."
|
||||
msgstr "Uma lista separada por vírgula de nomes de taxonomias personalizadas a serem incluídos no índice."
|
||||
|
||||
#: relevanssi.php:2260
|
||||
msgid ""
|
||||
"Check this to show more information on where the search hits were\n"
|
||||
"\t\tmade. Requires custom snippets to work."
|
||||
msgstr "Marque esta opção para exibir mais informações sobre onde os termos buscados foram encontrados. Para essa opção funcionar, é preciso habilitar os resumos personalizados."
|
||||
|
||||
#: relevanssi.php:2271
|
||||
msgid ""
|
||||
"Straight search matches just the term. Fuzzy search matches everything\n"
|
||||
"\t\tthat begins or ends with the search term."
|
||||
msgstr "Busca direta encontra apenas o termo buscado. Busca fuzzy irá encontrar tudo que começa ou termina com o termo buscado."
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2275
|
||||
msgid ""
|
||||
"If checked, Relevanssi will expand shortcodes in post content\n"
|
||||
"\t\tbefore indexing. Otherwise shortcodes will be stripped. If you use shortcodes to\n"
|
||||
"\t\tinclude dynamic content, Relevanssi will not keep the index updated, the index will\n"
|
||||
"\t\treflect the status of the shortcode content at the moment of indexing."
|
||||
msgstr "Se esta opção estiver marcada, Relevanssi irá converter os shortcodes no conteúdo do post antes de indexar. Caso contrário, os shortcodes serão removidos. Se você utiliza shortcodes para incluir conteúdo dinâmico, Relevanssi não manterá o índice atualizado. Ou seja, será utilizado o conteúdo gerado pelo shortcode no momento da indexação."
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2281
|
||||
msgid ""
|
||||
"If you want to uninstall the plugin, start by clicking the button\n"
|
||||
"\t\tbelow to wipe clean the options and tables created by the plugin, then remove it from\n"
|
||||
"\t\tthe plugins list."
|
||||
msgstr "Se quiser desinstalar o plugin, comece clicando no botão abaixo para remover todas as opções e todas as tabelas criadas pelo plugin, e então remova-o da lista de plugins."
|
||||
|
||||
#: relevanssi.php:2172
|
||||
msgid "Index and search your posts' authors:"
|
||||
msgstr "Indexar e buscar os autores dos posts:"
|
||||
|
||||
#: relevanssi.php:2173
|
||||
msgid ""
|
||||
"If checked, Relevanssi will also index and search the authors of your\n"
|
||||
"\t\tposts. Author display name will be indexed. Remember to rebuild the index if you change\n"
|
||||
"\t\tthis option!"
|
||||
msgstr "Se esta opção estiver marcada, Relevanssi irá indexar e realizar buscas nos autores de seus posts. Lembre-se de reconstruir o índice se você mudar esta opção!"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2286
|
||||
msgid "State of the Index"
|
||||
msgstr "Estatísticas do Índice"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2287
|
||||
msgid "Highest post ID indexed"
|
||||
msgstr "Último ID indexado"
|
||||
|
||||
#: relevanssi.php:2288
|
||||
msgid "Documents in the index"
|
||||
msgstr "Registros no índice"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2289
|
||||
msgid "Basic options"
|
||||
msgstr "Opções Básicas"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2291
|
||||
msgid "Default operator for the search?"
|
||||
msgstr "Operador padrão para a busca?"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2292
|
||||
msgid "AND - require all terms"
|
||||
msgstr "E - necessita de todos os termos"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2293
|
||||
msgid "OR - any term present is enough"
|
||||
msgstr "OU - qualquer termo presente é o bastante"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2294
|
||||
msgid "If you choose AND and the search finds no matches, it will automatically do an OR search."
|
||||
msgstr "Se escolher E e a busca não encontrar resultados, uma nova busca do tipo OU será feita automaticamente."
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2296
|
||||
msgid "Don't log queries from these users:"
|
||||
msgstr "Não armazenar registros de buscas destes usuários:"
|
||||
|
||||
#: relevanssi.php:2297
|
||||
msgid "Comma-separated list of user ids that will not be logged."
|
||||
msgstr "Uma lista separada por vírgula de usuários que não terão suas buscas registradas."
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2299
|
||||
msgid "Synonyms"
|
||||
msgstr "Sinônimos"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2300
|
||||
msgid "Add synonyms here in 'key = value' format. When searching with the OR operator, any search of 'key' will be expanded to include 'value' as well. Using phrases is possible. The key-value pairs work in one direction only, but you can of course repeat the same pair reversed."
|
||||
msgstr "Adicione sinônimos no formato \"chave = valor\". Quando for feita uma busca do tipo OU, qualquer busca por <strong>\"chave\"</strong> será expandida para incluir <strong>\"valor\"</strong> também. É possível utilizar frases. Os pares chave-valor funcionam apenas em uma direção, mas claro que você pode repetir o mesmo par em ordem inversa."
|
||||
|
||||
#: relevanssi.php:2177
|
||||
msgid "Index and search post excerpts:"
|
||||
msgstr "Indexar e buscar os resumos dos posts:"
|
||||
|
||||
#: relevanssi.php:2178
|
||||
msgid ""
|
||||
"If checked, Relevanssi will also index and search the excerpts of your\n"
|
||||
"\t\tposts.Remember to rebuild the index if you change this option!"
|
||||
msgstr "Se esta opção estiver marcada, Relevanssi irá indexar e realizar buscas nos resumos de seus posts. Lembre-se de reconstruir o índice se você mudar esta opção!"
|
||||
|
||||
# @ relevanssi
|
||||
#: relevanssi.php:2263
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Use %body%, %title%, %tags% and %comments% to display the number of\n"
|
||||
"\t\thits (in different parts of the post), %total% for total hits, %score% to display the document weight and %terms% to\n"
|
||||
"\t\tshow how many hits each search term got. No double quotes (\") allowed!"
|
||||
msgstr "Utilize %body%, %title%, %tags% e %comments% para exibir o número de hits, %total% para o total de hits, %score% para exibir a relevância e %terms% para exibir quantas vezes cada termo buscado foi encontrado. Aspas duplas (\") não são permitidas aqui!"
|
||||
|
||||
#~ msgid "Save"
|
||||
#~ msgstr "Gravar"
|
||||
#~ msgid ""
|
||||
#~ "Use %body%, %title%, %tags%, %comments% and %score% to display the number "
|
||||
#~ "of hits and the document weight."
|
||||
#~ msgstr ""
|
||||
#~ "Use %body%, %title%, %tags%, %comments% e %score% para exibir o número de "
|
||||
#~ "hits e o peso do resultado."
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -0,0 +1,148 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Mikko Saari <mikko@mikkosaari.fi>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fi\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/index.js:151
|
||||
msgid "not this"
|
||||
msgstr "ei tätä"
|
||||
|
||||
#: src/index.js:174
|
||||
msgid "use this"
|
||||
msgstr "käytä tätä"
|
||||
|
||||
#: src/index.js:199
|
||||
msgid "How Relevanssi sees this post"
|
||||
msgstr "Kuinka Relevanssi näkee artikkelin"
|
||||
|
||||
#: src/index.js:203
|
||||
msgid "Title:"
|
||||
msgstr "Otsikko:"
|
||||
|
||||
#: src/index.js:210
|
||||
msgid "Content:"
|
||||
msgstr "Sisältö:"
|
||||
|
||||
#: src/index.js:217
|
||||
msgid "Author:"
|
||||
msgstr "Tekijä:"
|
||||
|
||||
#: src/index.js:224
|
||||
msgid "Categories:"
|
||||
msgstr "Aiheet:"
|
||||
|
||||
#: src/index.js:231
|
||||
msgid "Tags:"
|
||||
msgstr "Avainsanat:"
|
||||
|
||||
#: src/index.js:238
|
||||
msgid "Other taxonomies:"
|
||||
msgstr "Muut taksonomiat:"
|
||||
|
||||
#: src/index.js:245
|
||||
msgid "Comments:"
|
||||
msgstr "Kommentit:"
|
||||
|
||||
#: src/index.js:252
|
||||
msgid "Custom fields:"
|
||||
msgstr "Avainkentät:"
|
||||
|
||||
#: src/index.js:259
|
||||
msgid "Excerpt:"
|
||||
msgstr "Ote:"
|
||||
|
||||
#: src/index.js:266
|
||||
msgid "Links to this post:"
|
||||
msgstr "Sisäiset linkit:"
|
||||
|
||||
#: src/index.js:273
|
||||
msgid "MySQL columns:"
|
||||
msgstr "MySQL-sarakkeet:"
|
||||
|
||||
#: src/index.js:281
|
||||
msgid "Reason this post is not indexed:"
|
||||
msgstr "Miksi tätä artikkelia ei ole indeksoitu:"
|
||||
|
||||
#: src/index.js:290
|
||||
msgid "Pinning"
|
||||
msgstr "Artikkelin kiinnittäminen"
|
||||
|
||||
#: src/index.js:294
|
||||
msgid "Pin this post for all searches it appears in."
|
||||
msgstr "Kiinnitä tämä artikkeli kärkeen kaikissa hauissa, joissa se esiintyy."
|
||||
|
||||
#: src/index.js:304
|
||||
msgid ""
|
||||
"A comma-separated list of single word keywords or multi-word phrases. If any "
|
||||
"of these keywords are present in the search query, this post will be moved "
|
||||
"on top of the search results."
|
||||
msgstr ""
|
||||
"Pilkuilla erotettu lista yksittäisiä hakusanoja tai monisanaisia "
|
||||
"hakulauseita. Jos joku näistä hakusanoista esiintyy käyttäjän haussa, tämä "
|
||||
"artikkeli kiinnitetään hakutulosten huipulle."
|
||||
|
||||
#: src/index.js:314
|
||||
msgid "Exclusion"
|
||||
msgstr "Artikkelien poissulkeminen"
|
||||
|
||||
#: src/index.js:319
|
||||
msgid "Exclude this post or page from the index."
|
||||
msgstr "Poista tämä artikkeli indeksistä."
|
||||
|
||||
#: src/index.js:329
|
||||
msgid ""
|
||||
"A comma-separated list of single word keywords or multi-word phrases. If any "
|
||||
"of these keywords are present in the search query, this post will be removed "
|
||||
"from the search results."
|
||||
msgstr ""
|
||||
"Pilkuilla erotettu lista yksittäisiä hakusanoja tai monisanaisia "
|
||||
"hakulauseita. Jos joku näistä hakusanoista esiintyy käyttäjän haussa, tämä "
|
||||
"artikkeli poistetaan hakutuloksista."
|
||||
|
||||
#: src/index.js:341
|
||||
msgid "Related posts"
|
||||
msgstr "Aiheeseen liittyvät artikkelit"
|
||||
|
||||
#: src/index.js:346
|
||||
msgid "Don't append the related posts to this page."
|
||||
msgstr "Älä lisää samankaltaisia artikkeleita tälle sivulle."
|
||||
|
||||
#: src/index.js:356
|
||||
msgid "Don't show this as a related post for any post."
|
||||
msgstr "Älä näytä tätä samankaltaisena artikkelina millään sivulla."
|
||||
|
||||
#: src/index.js:366
|
||||
msgid ""
|
||||
"A comma-separated list of keywords to use for the Related Posts feature. "
|
||||
"Anything entered here will used when searching for related posts. Using "
|
||||
"phrases with quotes is allowed, but will restrict the related posts to posts "
|
||||
"including that phrase."
|
||||
msgstr ""
|
||||
"Pilkulla erotettu lista avainsanoja samankaltaisten artikkelien etsimiseen. "
|
||||
"Tähän merkittyjä hakusanoja käytetään samankaltaisten artikkelien "
|
||||
"etsimiseen. Voit käyttää fraasihakua lainausmerkeillä, mutta se rajoittaa "
|
||||
"samankaltaiset artikkelit niihin, joissa fraasi esiintyy."
|
||||
|
||||
#: src/index.js:376
|
||||
msgid ""
|
||||
"A comma-separated list of post IDs to use as related posts for this post"
|
||||
msgstr ""
|
||||
"Pilkuilla erotettu lista tämän artikkelin liittyvinä artikkeleina "
|
||||
"käytettävien artikkelien ID-numeroista"
|
||||
|
||||
#: src/index.js:383
|
||||
msgid "Related posts for this post:"
|
||||
msgstr "Samankaltaiset artikkelit:"
|
||||
|
||||
#: src/index.js:386
|
||||
msgid "Excluded posts for this post:"
|
||||
msgstr "Älä käytä samankaltaisina artikkeleina tälle artikkelille:"
|
||||
@@ -0,0 +1,154 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"X-Generator: babel-plugin-makepot\n"
|
||||
|
||||
#: src/index.js:152
|
||||
msgid "not this"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:175
|
||||
msgid "use this"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:224
|
||||
msgid "How Relevanssi sees this post"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:228
|
||||
msgid "Title:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:235
|
||||
msgid "Content:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:242
|
||||
msgid "Author:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:249
|
||||
msgid "Categories:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:256
|
||||
msgid "Tags:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:263
|
||||
msgid "Other taxonomies:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:270
|
||||
msgid "Comments:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:277
|
||||
msgid "Custom fields:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:284
|
||||
msgid "Excerpt:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:291
|
||||
msgid "Links to this post:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:298
|
||||
msgid "MySQL columns:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:306
|
||||
msgid "Reason this post is not indexed:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:315
|
||||
msgid "Pinning"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:319
|
||||
msgid "Pin this post for all searches it appears in."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:338
|
||||
msgid ""
|
||||
"If any of these keywords are present in the search query, this post will be "
|
||||
"moved on top of the search results."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:343
|
||||
msgid ""
|
||||
"You can add weights to pinned keywords like this: 'keyword (100)'. The post "
|
||||
"with the highest weight will be sorted first if there are multiple posts "
|
||||
"pinned to the same keyword."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:349
|
||||
msgid "Exclusion"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:354
|
||||
msgid "Exclude this post or page from the index."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:364
|
||||
msgid "Ignore post content in the indexing."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:374
|
||||
msgid "A comma-separated list of single word keywords or multi-word phrases."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:383
|
||||
msgid ""
|
||||
"If any of these keywords are present in the search query, this post will be "
|
||||
"removed from the search results."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:391
|
||||
msgid "Related posts"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:396
|
||||
msgid "Don't append the related posts to this page."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:406
|
||||
msgid "Don't show this as a related post for any post."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:416
|
||||
msgid "A comma-separated list of keywords to use for the Related Posts feature."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:425
|
||||
msgid ""
|
||||
"Anything entered here will used when searching for related posts. Using "
|
||||
"phrases with quotes is allowed, but will restrict the related posts to "
|
||||
"posts including that phrase."
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:431
|
||||
msgid "A comma-separated list of post IDs to use as related posts for this post"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:438
|
||||
msgid "Related posts for this post:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:441
|
||||
msgid "Excluded posts for this post:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:446
|
||||
msgid "Insights"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:448
|
||||
msgid "The most common search terms used to find this post:"
|
||||
msgstr ""
|
||||
|
||||
#: src/index.js:455
|
||||
msgid "Low-ranking search terms used to find this post:"
|
||||
msgstr ""
|
||||
@@ -0,0 +1 @@
|
||||
{"translation-revision-date":"2023-04-23 03:33:04+0000","generator":"GlotPress\/4.0.0-alpha.3","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n != 1;","lang":"sv_SE"},"Insights":["Inblickar"]}},"comment":{"reference":"index.js"}}
|
||||
470
wp/wp-content/plugins/relevanssi-premium/lib/admin-ajax.php
Normal file
470
wp/wp-content/plugins/relevanssi-premium/lib/admin-ajax.php
Normal file
@@ -0,0 +1,470 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/admin-ajax.php
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_action( 'wp_ajax_relevanssi_truncate_index', 'relevanssi_truncate_index_ajax_wrapper' );
|
||||
add_action( 'wp_ajax_relevanssi_index_posts', 'relevanssi_index_posts_ajax_wrapper' );
|
||||
add_action( 'wp_ajax_relevanssi_count_posts', 'relevanssi_count_posts_ajax_wrapper' );
|
||||
add_action( 'wp_ajax_relevanssi_count_missing_posts', 'relevanssi_count_missing_posts_ajax_wrapper' );
|
||||
add_action( 'wp_ajax_relevanssi_list_categories', 'relevanssi_list_categories' );
|
||||
add_action( 'wp_ajax_relevanssi_admin_search', 'relevanssi_admin_search' );
|
||||
add_action( 'wp_ajax_relevanssi_update_counts', 'relevanssi_update_counts' );
|
||||
add_action( 'wp_ajax_nopriv_relevanssi_update_counts', 'relevanssi_update_counts' );
|
||||
add_action( 'wp_ajax_relevanssi_list_custom_fields', 'relevanssi_list_custom_fields' );
|
||||
|
||||
/**
|
||||
* Checks if current user can access Relevanssi options.
|
||||
*
|
||||
* If the current user doesn't have sufficient access to Relevanssi options,
|
||||
* the function will die. If the user has access, nothing happens.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function relevanssi_current_user_can_access_options() {
|
||||
/**
|
||||
* Filters the capability required to access Relevanssi options.
|
||||
*
|
||||
* @param string The capability required. Default 'manage_options'.
|
||||
*/
|
||||
if ( ! current_user_can( apply_filters( 'relevanssi_options_capability', 'manage_options' ) ) ) {
|
||||
wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'relevanssi' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the Relevanssi index.
|
||||
*
|
||||
* Wipes the index clean using relevanssi_truncate_index().
|
||||
*/
|
||||
function relevanssi_truncate_index_ajax_wrapper() {
|
||||
check_ajax_referer( 'relevanssi_indexing_nonce', 'security' );
|
||||
relevanssi_current_user_can_access_options();
|
||||
|
||||
$response = relevanssi_truncate_index();
|
||||
echo wp_json_encode( $response );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes posts in AJAX context.
|
||||
*
|
||||
* AJAX wrapper for indexing posts. Parses the arguments, uses the
|
||||
* relevanssi_build_index() to do the hard work, then creates the AJAX response.
|
||||
*/
|
||||
function relevanssi_index_posts_ajax_wrapper() {
|
||||
check_ajax_referer( 'relevanssi_indexing_nonce', 'security' );
|
||||
relevanssi_current_user_can_access_options();
|
||||
|
||||
$completed = absint( $_POST['completed'] );
|
||||
$total = absint( $_POST['total'] );
|
||||
$offset = absint( $_POST['offset'] );
|
||||
$limit = absint( $_POST['limit'] );
|
||||
$extend = strval( $_POST['extend'] );
|
||||
|
||||
if ( 'true' === $extend ) {
|
||||
$extend = true;
|
||||
}
|
||||
|
||||
if ( $limit < 1 ) {
|
||||
$limit = 1;
|
||||
}
|
||||
|
||||
$response = array();
|
||||
|
||||
$is_ajax = true;
|
||||
$verbose = false;
|
||||
if ( $extend ) {
|
||||
$offset = true;
|
||||
}
|
||||
|
||||
$indexing_response = relevanssi_build_index( $offset, $verbose, $limit, $is_ajax );
|
||||
|
||||
if ( $indexing_response['indexing_complete'] ) {
|
||||
$response['completed'] = 'done';
|
||||
$response['percentage'] = 100;
|
||||
$completed += $indexing_response['indexed'];
|
||||
$response['total_posts'] = $completed;
|
||||
$processed = $total;
|
||||
} else {
|
||||
$completed += $indexing_response['indexed'];
|
||||
$response['completed'] = $completed;
|
||||
|
||||
if ( true === $offset ) {
|
||||
$processed = $completed;
|
||||
} else {
|
||||
$offset = $offset + $limit;
|
||||
$processed = $offset;
|
||||
}
|
||||
|
||||
if ( $total > 0 ) {
|
||||
$response['percentage'] = $processed / $total * 100;
|
||||
} else {
|
||||
$response['percentage'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$response['feedback'] = sprintf(
|
||||
// translators: Number of posts indexed on this go, total number of posts indexed so far, number of posts processed on this go, total number of posts to process.
|
||||
_n(
|
||||
'Indexed %1$d post (total %2$d), processed %3$d / %4$d.',
|
||||
'Indexed %1$d posts (total %2$d), processed %3$d / %4$d.',
|
||||
$indexing_response['indexed'],
|
||||
'relevanssi'
|
||||
),
|
||||
$indexing_response['indexed'],
|
||||
$completed,
|
||||
$processed,
|
||||
$total
|
||||
) . "\n";
|
||||
$response['offset'] = $offset;
|
||||
|
||||
echo wp_json_encode( $response );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the posts to index.
|
||||
*
|
||||
* AJAX wrapper for relevanssi_count_total_posts().
|
||||
*/
|
||||
function relevanssi_count_posts_ajax_wrapper() {
|
||||
relevanssi_current_user_can_access_options();
|
||||
|
||||
$count = relevanssi_count_total_posts();
|
||||
echo wp_json_encode( $count );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the posts missing from the index.
|
||||
*
|
||||
* AJAX wrapper for relevanssi_count_missing_posts().
|
||||
*/
|
||||
function relevanssi_count_missing_posts_ajax_wrapper() {
|
||||
relevanssi_current_user_can_access_options();
|
||||
|
||||
$count = relevanssi_count_missing_posts();
|
||||
echo wp_json_encode( $count );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists categories.
|
||||
*
|
||||
* AJAX wrapper for get_categories().
|
||||
*/
|
||||
function relevanssi_list_categories() {
|
||||
relevanssi_current_user_can_access_options();
|
||||
|
||||
$categories = get_categories(
|
||||
array(
|
||||
'taxonomy' => 'category',
|
||||
'hide_empty' => false,
|
||||
)
|
||||
);
|
||||
echo wp_json_encode( $categories );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an admin search.
|
||||
*
|
||||
* Performs an admin dashboard search.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
function relevanssi_admin_search() {
|
||||
check_ajax_referer( 'relevanssi_admin_search_nonce', 'security' );
|
||||
/**
|
||||
* Filters the capability required to access Relevanssi admin search page.
|
||||
*
|
||||
* @param string The capability required. Default 'edit_posts'.
|
||||
*/
|
||||
if ( ! current_user_can( apply_filters( 'relevanssi_admin_search_capability', 'edit_posts' ) ) ) {
|
||||
wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'relevanssi' ) );
|
||||
}
|
||||
|
||||
$args = array();
|
||||
if ( isset( $_POST['args'] ) ) {
|
||||
parse_str( $_POST['args'], $args );
|
||||
}
|
||||
if ( isset( $_POST['posts_per_page'] ) ) {
|
||||
$posts_per_page = intval( $_POST['posts_per_page'] );
|
||||
if ( $posts_per_page > 0 ) {
|
||||
$args['posts_per_page'] = $posts_per_page;
|
||||
}
|
||||
}
|
||||
if ( isset( $_POST['post_types'] ) ) {
|
||||
$post_type = $_POST['post_types'];
|
||||
$args['post_types'] = $post_type;
|
||||
}
|
||||
if ( isset( $_POST['offset'] ) ) {
|
||||
$offset = intval( $_POST['offset'] );
|
||||
if ( $offset > 0 ) {
|
||||
$args['offset'] = $offset;
|
||||
}
|
||||
}
|
||||
if ( isset( $_POST['s'] ) ) {
|
||||
$args['s'] = $_POST['s'];
|
||||
}
|
||||
|
||||
$query = new WP_Query();
|
||||
$query->parse_query( $args );
|
||||
$query->set( 'relevanssi_admin_search', true );
|
||||
$query = apply_filters( 'relevanssi_modify_wp_query', $query );
|
||||
relevanssi_do_query( $query );
|
||||
|
||||
$results = relevanssi_admin_search_debugging_info( $query );
|
||||
|
||||
// Take the posts array and create a string out of it.
|
||||
$offset = 0;
|
||||
if ( isset( $query->query_vars['offset'] ) ) {
|
||||
$offset = $query->query_vars['offset'];
|
||||
}
|
||||
$results .= relevanssi_admin_search_format_posts( $query->posts, $query->found_posts, $offset, $args['s'] );
|
||||
|
||||
echo wp_json_encode( $results );
|
||||
wp_die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the posts for admin search.
|
||||
*
|
||||
* Results are presented as an ordered list of posts. The format is very basic, and
|
||||
* can be modified with the 'relevanssi_admin_search_element' filter hook.
|
||||
*
|
||||
* @param array $posts The posts array.
|
||||
* @param int $total The number of posts found in total.
|
||||
* @param int $offset Offset value.
|
||||
* @param string $query The search query.
|
||||
*
|
||||
* @return string The formatted posts.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
function relevanssi_admin_search_format_posts( $posts, $total, $offset, $query ) {
|
||||
$result = '<h3>' . __( 'Results', 'relevanssi' ) . '</h3>';
|
||||
$start = $offset + 1;
|
||||
$end = $offset + count( $posts );
|
||||
// Translators: %1$d is the total number of posts found, %2$d is the current search result count, %3$d is the offset.
|
||||
$result .= '<p>' . sprintf( __( 'Found a total of %1$d posts, showing posts %2$d–%3$s.', 'relevanssi' ), $total, $start, '<span id="offset">' . $end . '</span>' ) . '</p>';
|
||||
if ( $offset > 0 ) {
|
||||
$result .= sprintf( '<button type="button" id="prev_page">%s</button>', __( 'Previous page', 'relevanssi' ) );
|
||||
}
|
||||
if ( count( $posts ) + $offset < $total ) {
|
||||
$result .= sprintf( '<button type="button" id="next_page">%s</button>', __( 'Next page', 'relevanssi' ) );
|
||||
}
|
||||
$result .= '<ol start="' . $start . '">';
|
||||
|
||||
$score_label = __( 'Score:', 'relevanssi' );
|
||||
|
||||
foreach ( $posts as $post ) {
|
||||
$blog_name = '';
|
||||
if ( isset( $post->blog_id ) && function_exists( 'switch_to_blog' ) ) {
|
||||
switch_to_blog( $post->blog_id );
|
||||
$blog_name = get_bloginfo( 'name' ) . ': ';
|
||||
}
|
||||
$permalink = get_permalink( $post->ID );
|
||||
$edit_url = get_edit_post_link( $post->ID );
|
||||
$post_type = $post->post_type;
|
||||
if ( isset( $post->relevanssi_link ) ) {
|
||||
$permalink = $post->relevanssi_link;
|
||||
}
|
||||
if ( 'user' === $post->post_type ) {
|
||||
$edit_url = get_edit_user_link( $post->ID );
|
||||
}
|
||||
if ( empty( $edit_url ) ) {
|
||||
if ( isset( $post->term_id ) ) {
|
||||
$edit_url = get_edit_term_link( $post->term_id, $post->post_type );
|
||||
}
|
||||
}
|
||||
$title = sprintf( '<a href="%1$s">%2$s %3$s</a>', $permalink, $post->post_title, $post_type );
|
||||
$edit_link = '';
|
||||
if ( current_user_can( 'edit_post', $post->ID ) ) {
|
||||
$edit_link = sprintf( '(<a href="%1$s">%2$s %3$s</a>)', $edit_url, __( 'Edit', 'relevanssi' ), $post_type );
|
||||
}
|
||||
|
||||
$pinning_buttons = '';
|
||||
$pinned = '';
|
||||
|
||||
if ( function_exists( 'relevanssi_admin_search_pinning' ) ) {
|
||||
// Relevanssi Premium adds pinning features to the admin search.
|
||||
list( $pinning_buttons, $pinned ) = relevanssi_admin_search_pinning( $post, $query );
|
||||
}
|
||||
|
||||
$post_element = <<<EOH
|
||||
<li>$blog_name <strong>$title</strong> $edit_link $pinning_buttons <br />
|
||||
$post->post_excerpt<br />
|
||||
$score_label $post->relevance_score $pinned</li>
|
||||
EOH;
|
||||
/**
|
||||
* Filters the admin search results element.
|
||||
*
|
||||
* The post element is a <li> element. Feel free to edit the element any
|
||||
* way you want to.
|
||||
*
|
||||
* @param string $post_element The post element.
|
||||
* @param object $post The post object.
|
||||
*/
|
||||
$result .= apply_filters( 'relevanssi_admin_search_element', $post_element, $post );
|
||||
if ( isset( $post->blog_id ) && function_exists( 'restore_current_blog' ) ) {
|
||||
restore_current_blog();
|
||||
}
|
||||
}
|
||||
$result .= '</ol>';
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows debugging information about the search.
|
||||
*
|
||||
* Formats the WP_Query parameters, looks at some filter hooks and presents the
|
||||
* information in an easy-to-read format.
|
||||
*
|
||||
* @param WP_Query $query The WP_Query object.
|
||||
*
|
||||
* @return string The formatted debugging information.
|
||||
*
|
||||
* @since 2.2.0
|
||||
*/
|
||||
function relevanssi_admin_search_debugging_info( $query ) {
|
||||
$result = '<div id="debugging">';
|
||||
$result .= '<h3>' . __( 'Query variables', 'relevanssi' ) . '</h3>';
|
||||
$result .= '<ul style="list-style: disc; margin-left: 1.5em">';
|
||||
foreach ( $query->query_vars as $key => $value ) {
|
||||
if ( 'tax_query' === $key ) {
|
||||
$result .= '<li>tax_query:<ul style="list-style: disc; margin-left: 1.5em">';
|
||||
$result .= implode(
|
||||
'',
|
||||
array_map(
|
||||
function ( $row ) {
|
||||
$result = '';
|
||||
if ( is_array( $row ) ) {
|
||||
foreach ( $row as $row_key => $row_value ) {
|
||||
$result .= "<li>$row_key: $row_value</li>";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
},
|
||||
$value
|
||||
)
|
||||
);
|
||||
$result .= '</ul></li>';
|
||||
} else {
|
||||
if ( is_array( $value ) ) {
|
||||
$value = relevanssi_flatten_array( $value );
|
||||
}
|
||||
if ( empty( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
$result .= "<li>$key: $value</li>";
|
||||
}
|
||||
}
|
||||
if ( ! empty( $query->tax_query ) ) {
|
||||
$result .= '<li>tax_query:<ul style="list-style: disc; margin-left: 1.5em">';
|
||||
foreach ( $query->tax_query as $tax_query ) {
|
||||
if ( ! is_array( $tax_query ) ) {
|
||||
continue;
|
||||
}
|
||||
foreach ( $tax_query as $key => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$value = relevanssi_flatten_array( $value );
|
||||
}
|
||||
$result .= "<li>$key: $value</li>";
|
||||
}
|
||||
}
|
||||
$result .= '</ul></li>';
|
||||
}
|
||||
$result .= '</ul>';
|
||||
|
||||
global $wp_filter;
|
||||
|
||||
$filters = array(
|
||||
'relevanssi_search_ok',
|
||||
'relevanssi_modify_wp_query',
|
||||
'relevanssi_search_filters',
|
||||
'relevanssi_where',
|
||||
'relevanssi_join',
|
||||
'relevanssi_fuzzy_query',
|
||||
'relevanssi_exact_match_bonus',
|
||||
'relevanssi_query_filter',
|
||||
'relevanssi_match',
|
||||
'relevanssi_post_ok',
|
||||
'relevanssi_search_again',
|
||||
'relevanssi_results',
|
||||
'relevanssi_orderby',
|
||||
'relevanssi_order',
|
||||
'relevanssi_default_tax_query_relation',
|
||||
'relevanssi_hits_filter',
|
||||
);
|
||||
|
||||
$result .= '<h3>' . __( 'Filters', 'relevanssi' ) . '</h3>';
|
||||
$result .= '<button type="button" id="show_filters">' . __( 'show', 'relevanssi' ) . '</button>';
|
||||
$result .= '<button type="button" id="hide_filters" style="display: none">' . __( 'hide', 'relevanssi' ) . '</button>';
|
||||
$result .= '<div id="relevanssi_filter_list">';
|
||||
foreach ( $filters as $filter ) {
|
||||
if ( isset( $wp_filter[ $filter ] ) ) {
|
||||
$result .= '<h4>' . $filter . '</h4>';
|
||||
$result .= '<ul style="list-style: disc; margin-left: 1.5em">';
|
||||
foreach ( $wp_filter[ $filter ] as $priority => $functions ) {
|
||||
foreach ( $functions as $function ) {
|
||||
if ( $function['function'] instanceof Closure ) {
|
||||
$function['function'] = 'Anonymous function';
|
||||
}
|
||||
$result .= "<li>$priority: " . $function['function'] . '</li>';
|
||||
}
|
||||
}
|
||||
$result .= '</ul>';
|
||||
}
|
||||
}
|
||||
$result .= '</div>';
|
||||
$result .= '</div>';
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates count options.
|
||||
*
|
||||
* Updates 'relevanssi_doc_count', 'relevanssi_terms_count' (and in Premium
|
||||
* 'relevanssi_user_count' and 'relevanssi_taxterm_count'). These are slightly
|
||||
* expensive queries, so they are updated when necessary as a non-blocking AJAX
|
||||
* action and stored in options for quick retrieval.
|
||||
*
|
||||
* @global object $wpdb The WordPress database interface.
|
||||
* @global array $relevanssi_variables The Relevanssi global variable, used for table names.
|
||||
*/
|
||||
function relevanssi_update_counts() {
|
||||
global $wpdb, $relevanssi_variables;
|
||||
|
||||
relevanssi_update_doc_count();
|
||||
|
||||
$terms_count = $wpdb->get_var( 'SELECT COUNT(*) FROM ' . $relevanssi_variables['relevanssi_table'] ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
||||
update_option( 'relevanssi_terms_count', is_null( $terms_count ) ? 0 : $terms_count, false );
|
||||
|
||||
if ( RELEVANSSI_PREMIUM ) {
|
||||
$user_count = $wpdb->get_var( 'SELECT COUNT(DISTINCT item) FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE type = 'user'" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
||||
$taxterm_count = $wpdb->get_var( 'SELECT COUNT(DISTINCT item) FROM ' . $relevanssi_variables['relevanssi_table'] . " WHERE (type != 'post' AND type != 'attachment' AND type != 'user')" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
update_option( 'relevanssi_user_count', is_null( $user_count ) ? 0 : $user_count, false );
|
||||
update_option( 'relevanssi_taxterm_count', is_null( $taxterm_count ) ? 0 : $taxterm_count, false );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a comma-separated list of indexed custom field names.
|
||||
*
|
||||
* @uses relevanssi_list_all_indexed_custom_fields()
|
||||
*/
|
||||
function relevanssi_list_custom_fields() {
|
||||
$response = relevanssi_list_all_indexed_custom_fields();
|
||||
|
||||
echo wp_json_encode( $response );
|
||||
wp_die();
|
||||
}
|
||||
540
wp/wp-content/plugins/relevanssi-premium/lib/admin_scripts.js
Normal file
540
wp/wp-content/plugins/relevanssi-premium/lib/admin_scripts.js
Normal file
@@ -0,0 +1,540 @@
|
||||
/* Confirmation for copying options between blogs */
|
||||
|
||||
jQuery(document).ready(function ($) {
|
||||
$("#copy_config").on("submit", function () {
|
||||
var c = confirm(relevanssi.confirm)
|
||||
return c //you can just return c because it will be true or false
|
||||
})
|
||||
|
||||
$("#removeallstopwords").on("click", function () {
|
||||
var c = confirm(relevanssi.confirm_stopwords)
|
||||
return c
|
||||
})
|
||||
|
||||
$("#delete_query").on("click", function () {
|
||||
var c = confirm(relevanssi.confirm_delete_query)
|
||||
return c
|
||||
})
|
||||
|
||||
$("#list_custom_fields").on("click", function () {
|
||||
var results = $("#relevanssi_custom_field_list")
|
||||
var data = {
|
||||
action: "relevanssi_list_custom_fields",
|
||||
}
|
||||
jQuery.post(ajaxurl, data, function (response) {
|
||||
console.log(response)
|
||||
results.html('<p>' + JSON.parse(response) + '</p>')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
jQuery(document).ready(function ($) {
|
||||
$(".color-field").wpColorPicker()
|
||||
|
||||
var txtcol_control = $("#tr_relevanssi_txt_col")
|
||||
var bgcol_control = $("#tr_relevanssi_bg_col")
|
||||
var class_control = $("#tr_relevanssi_class")
|
||||
var css_control = $("#tr_relevanssi_css")
|
||||
|
||||
$("#relevanssi_highlight").on("change", function () {
|
||||
txtcol_control.addClass("screen-reader-text")
|
||||
bgcol_control.addClass("screen-reader-text")
|
||||
class_control.addClass("screen-reader-text")
|
||||
css_control.addClass("screen-reader-text")
|
||||
|
||||
if (this.value == "col") txtcol_control.toggleClass("screen-reader-text")
|
||||
if (this.value == "bgcol") bgcol_control.toggleClass("screen-reader-text")
|
||||
if (this.value == "class") class_control.toggleClass("screen-reader-text")
|
||||
if (this.value == "css") css_control.toggleClass("screen-reader-text")
|
||||
})
|
||||
|
||||
$("#relevanssi_hilite_title").on("click", function () {
|
||||
$("#title_description").toggleClass("screen-reader-text", !this.checked)
|
||||
})
|
||||
|
||||
var or_fallback = $("#orfallback")
|
||||
$("#relevanssi_implicit_operator").on("change", function () {
|
||||
or_fallback.toggleClass("screen-reader-text")
|
||||
})
|
||||
|
||||
var index_subscribers = $("#index_subscribers")
|
||||
var user_extra_fields = $("#user_extra_fields")
|
||||
$("#relevanssi_index_users").on("click", function () {
|
||||
$("#user_profile_notice").toggleClass("screen-reader-text", !this.checked)
|
||||
index_subscribers.toggleClass("screen-reader-text", !this.checked)
|
||||
user_extra_fields.toggleClass("screen-reader-text", !this.checked)
|
||||
})
|
||||
|
||||
var taxonomies = $("#taxonomies")
|
||||
$("#relevanssi_index_taxonomies").on("click", function () {
|
||||
taxonomies.toggleClass("screen-reader-text", !this.checked)
|
||||
})
|
||||
|
||||
var post_type_archives = $("#posttypearchives")
|
||||
$("#relevanssi_index_post_type_archives").on("click", function () {
|
||||
post_type_archives.toggleClass("screen-reader-text", !this.checked)
|
||||
})
|
||||
|
||||
var fields_content = $("#index_field_input")
|
||||
var fields_select = $("#relevanssi_index_fields_select")
|
||||
fields_select.on("change", function () {
|
||||
if (this.value == "some") fields_content.show()
|
||||
if (this.value != "some") fields_content.hide()
|
||||
})
|
||||
|
||||
var index_images = $("#row_index_image_files")
|
||||
var index_attachments = $("#relevanssi_index_type_attachment")
|
||||
index_attachments.on("click", function () {
|
||||
if (this.checked) index_images.show()
|
||||
if (!this.checked) index_images.hide()
|
||||
})
|
||||
|
||||
$("#show_advanced_indexing").on("click", function (e) {
|
||||
$("#advanced_indexing").toggleClass("screen-reader-text")
|
||||
$("#hide_advanced_indexing").show()
|
||||
$("#show_advanced_indexing").hide()
|
||||
})
|
||||
|
||||
$("#hide_advanced_indexing").on("click", function (e) {
|
||||
$("#advanced_indexing").toggleClass("screen-reader-text")
|
||||
$("#show_advanced_indexing").show()
|
||||
$("#hide_advanced_indexing").hide()
|
||||
})
|
||||
|
||||
$("#indexing_tab :input").on("change", function (e) {
|
||||
$("#build_index").attr("disabled", "disabled")
|
||||
var relevanssi_note = $("#relevanssi-note")
|
||||
relevanssi_note.show()
|
||||
relevanssi_note.html('<p class="description important">' + relevanssi.options_changed + '</p>')
|
||||
})
|
||||
|
||||
$("#relevanssi_default_orderby").on("change", function (e) {
|
||||
if (this.value == "post_date") {
|
||||
$("#relevanssi_throttle").prop("checked", false)
|
||||
}
|
||||
$("#throttle_disabled").toggleClass("screen-reader-text")
|
||||
$("#throttle_enabled").toggleClass("screen-reader-text")
|
||||
})
|
||||
|
||||
$("#relevanssi_show_pdf_errors").on("click", function (e) {
|
||||
var error_box = $("#relevanssi_pdf_errors")
|
||||
error_box.toggle()
|
||||
var data = {
|
||||
action: "relevanssi_get_pdf_errors",
|
||||
}
|
||||
jQuery.post(ajaxurl, data, function (response) {
|
||||
error_box.val(JSON.parse(response))
|
||||
})
|
||||
})
|
||||
|
||||
$("#relevanssi_excerpts").on("click", function () {
|
||||
$("#relevanssi_breakdown").toggleClass("relevanssi_disabled", !this.checked)
|
||||
$("#relevanssi_highlighting").toggleClass(
|
||||
"relevanssi_disabled",
|
||||
!this.checked
|
||||
)
|
||||
$("#tr_excerpt_custom_fields").toggleClass(
|
||||
"relevanssi_disabled",
|
||||
!this.checked
|
||||
)
|
||||
$("#tr_excerpt_allowable_tags").toggleClass(
|
||||
"relevanssi_disabled",
|
||||
!this.checked
|
||||
)
|
||||
$("#tr_excerpt_length").toggleClass("relevanssi_disabled", !this.checked)
|
||||
$("#tr_max_excerpts").toggleClass("relevanssi_disabled", !this.checked)
|
||||
$("#relevanssi_excerpt_length").attr("disabled", !this.checked)
|
||||
$("#relevanssi_excerpt_type").attr("disabled", !this.checked)
|
||||
$("#relevanssi_max_excerpts").attr("disabled", !this.checked)
|
||||
$("#relevanssi_excerpt_allowable_tags").attr("disabled", !this.checked)
|
||||
$("#relevanssi_excerpt_custom_fields").attr("disabled", !this.checked)
|
||||
$("#relevanssi_highlight").attr("disabled", !this.checked)
|
||||
$("#relevanssi_txt_col").attr("disabled", !this.checked)
|
||||
$("#relevanssi_bg_col").attr("disabled", !this.checked)
|
||||
$("#relevanssi_css").attr("disabled", !this.checked)
|
||||
$("#relevanssi_class").attr("disabled", !this.checked)
|
||||
$("#relevanssi_hilite_title").attr("disabled", !this.checked)
|
||||
$("#relevanssi_highlight_docs").attr("disabled", !this.checked)
|
||||
$("#relevanssi_highlight_comments").attr("disabled", !this.checked)
|
||||
$("#relevanssi_show_matches").attr("disabled", !this.checked)
|
||||
$("#relevanssi_show_matches_text").attr("disabled", !this.checked)
|
||||
$("#relevanssi_expand_highlights").attr("disabled", !this.checked)
|
||||
})
|
||||
|
||||
$("#relevanssi_excerpt_custom_fields").on("change", function () {
|
||||
$("#relevanssi_excerpt_specific_fields").attr("disabled", !this.checked)
|
||||
})
|
||||
|
||||
$("#relevanssi_searchblogs_all").on("click", function () {
|
||||
$("#relevanssi_searchblogs").attr("disabled", this.checked)
|
||||
})
|
||||
|
||||
var min_word_length = $("#relevanssi_min_word_length")
|
||||
min_word_length.on("change", function(e) {
|
||||
if ( min_word_length.val() < 1 ) {
|
||||
min_word_length.val(1)
|
||||
}
|
||||
if ( min_word_length.val() > 9 ) {
|
||||
min_word_length.val(9)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
var time = 0
|
||||
var intervalID = 0
|
||||
|
||||
function relevanssiUpdateClock() {
|
||||
time++
|
||||
var time_formatted = rlv_format_time(Math.round(time))
|
||||
document.getElementById("relevanssi_elapsed").innerHTML = time_formatted
|
||||
}
|
||||
|
||||
jQuery(document).ready(function ($) {
|
||||
$("#continue_indexing").on("click", function () {
|
||||
$("#relevanssi-progress").show()
|
||||
$("#results").show()
|
||||
$("#relevanssi-timer").show()
|
||||
$("#stateoftheindex").html(relevanssi.reload_state)
|
||||
$("#indexing_button_instructions").hide()
|
||||
var results = document.getElementById("results")
|
||||
results.value = ""
|
||||
|
||||
intervalID = window.setInterval(relevanssiUpdateClock, 1000)
|
||||
|
||||
var data = {
|
||||
action: "relevanssi_count_missing_posts",
|
||||
}
|
||||
console.log("Counting posts.")
|
||||
results.value += relevanssi.counting_posts + " "
|
||||
jQuery.post(ajaxurl, data, function (response) {
|
||||
count_response = JSON.parse(response)
|
||||
console.log("Counted " + count_response + " posts.")
|
||||
results.value += count_response + " " + relevanssi.posts_found + "\n"
|
||||
if (count_response > 0) {
|
||||
var args = {
|
||||
completed: 0,
|
||||
total: count_response,
|
||||
offset: 0,
|
||||
total_seconds: 0,
|
||||
limit: relevanssi_params.indexing_limit,
|
||||
adjust: relevanssi_params.indexing_adjust,
|
||||
extend: true,
|
||||
security: nonce.indexing_nonce,
|
||||
}
|
||||
process_indexing_step(args)
|
||||
} else {
|
||||
clearInterval(intervalID)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
function process_indexing_step(args) {
|
||||
// console.log(args.completed + " / " + args.total);
|
||||
var t0 = performance.now()
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_index_posts",
|
||||
completed: args.completed,
|
||||
total: args.total,
|
||||
offset: args.offset,
|
||||
limit: args.limit,
|
||||
adjust: args.adjust,
|
||||
extend: args.extend,
|
||||
security: args.security,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
console.log(response)
|
||||
if (response.completed == "done") {
|
||||
//console.log("response " + parseInt(response.total_posts));
|
||||
var results_textarea = document.getElementById("results")
|
||||
results_textarea.value += response.feedback
|
||||
|
||||
document.getElementById("relevanssi_estimated").innerHTML =
|
||||
relevanssi.notimeremaining
|
||||
|
||||
var hidden_posts = args.total - parseInt(response.total_posts)
|
||||
results_textarea.value +=
|
||||
relevanssi.indexing_complete +
|
||||
" " +
|
||||
hidden_posts +
|
||||
" " +
|
||||
relevanssi.excluded_posts
|
||||
results_textarea.scrollTop = results_textarea.scrollHeight
|
||||
jQuery(".rpi-progress div").animate(
|
||||
{
|
||||
width: response.percentage + "%",
|
||||
},
|
||||
50,
|
||||
function () {
|
||||
// Animation complete.
|
||||
}
|
||||
)
|
||||
|
||||
clearInterval(intervalID)
|
||||
} else {
|
||||
var t1 = performance.now()
|
||||
var time_seconds = (t1 - t0) / 1000
|
||||
time_seconds = Math.round(time_seconds * 100) / 100
|
||||
args.total_seconds += time_seconds
|
||||
|
||||
var estimated_time = rlv_format_approximate_time(
|
||||
Math.round(
|
||||
(args.total_seconds / response.percentage) * 100 -
|
||||
args.total_seconds
|
||||
)
|
||||
)
|
||||
|
||||
document.getElementById(
|
||||
"relevanssi_estimated"
|
||||
).innerHTML = estimated_time
|
||||
|
||||
if (args.adjust) {
|
||||
if (time_seconds < 2) {
|
||||
args.limit = args.limit * 2
|
||||
// current limit can be indexed in less than two seconds; double the limit
|
||||
} else if (time_seconds < 5) {
|
||||
args.limit += 5
|
||||
// current limit can be indexed in less than five seconds; up the limit
|
||||
} else if (time_seconds > 20) {
|
||||
args.limit = Math.round(args.limit / 2)
|
||||
if (args.limit < 1) args.limit = 1
|
||||
// current limit takes more than twenty seconds; halve the limit
|
||||
} else if (time_seconds > 10) {
|
||||
args.limit -= 5
|
||||
if (args.limit < 1) args.limit = 1
|
||||
// current limit takes more than ten seconds; reduce the limit
|
||||
}
|
||||
}
|
||||
|
||||
var results_textarea = document.getElementById("results")
|
||||
results_textarea.value += response.feedback
|
||||
results_textarea.scrollTop = results_textarea.scrollHeight
|
||||
var percentage_rounded = Math.round(response.percentage)
|
||||
|
||||
jQuery(".rpi-progress div").animate(
|
||||
{
|
||||
width: percentage_rounded + "%",
|
||||
},
|
||||
50,
|
||||
function () {
|
||||
// Animation complete.
|
||||
}
|
||||
)
|
||||
//console.log("Next step.");
|
||||
var new_args = {
|
||||
completed: parseInt(response.completed),
|
||||
total: args.total,
|
||||
offset: response.offset,
|
||||
total_seconds: args.total_seconds,
|
||||
limit: args.limit,
|
||||
adjust: args.adjust,
|
||||
extend: args.extend,
|
||||
security: args.security,
|
||||
}
|
||||
|
||||
process_indexing_step(new_args)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function rlv_format_time(total_seconds) {
|
||||
var hours = Math.floor(total_seconds / 3600)
|
||||
var minutes = Math.floor((total_seconds - hours * 3600) / 60)
|
||||
var seconds = total_seconds - hours * 3600 - minutes * 60
|
||||
|
||||
if (minutes < 10) minutes = "0" + minutes
|
||||
if (seconds < 10) seconds = "0" + seconds
|
||||
|
||||
return hours + ":" + minutes + ":" + seconds
|
||||
}
|
||||
|
||||
function rlv_format_approximate_time(total_seconds) {
|
||||
var hours = Math.floor(total_seconds / 3600)
|
||||
var minutes = Math.floor(total_seconds / 60)
|
||||
var seconds = total_seconds - hours * 3600 - minutes * 60
|
||||
|
||||
var time = ""
|
||||
if (minutes > 99) {
|
||||
hour_word = relevanssi.hours
|
||||
if (hours == 1) hour_word = relevanssi.hour
|
||||
time = relevanssi.about + " " + hours + " " + hour_word
|
||||
}
|
||||
if (minutes > 79 && minutes < 100) time = relevanssi.ninety_min
|
||||
if (minutes > 49 && minutes < 80) time = relevanssi.sixty_min
|
||||
if (minutes < 50) {
|
||||
if (seconds > 30) minutes += 1
|
||||
minute_word = relevanssi.minutes
|
||||
if (minutes == 1) minute_word = relevanssi.minute
|
||||
time = relevanssi.about + " " + minutes + " " + minute_word
|
||||
}
|
||||
if (minutes < 1) time = relevanssi.underminute
|
||||
|
||||
return time
|
||||
}
|
||||
|
||||
jQuery(document).ready(function ($) {
|
||||
$("#search").on("click", function (e) {
|
||||
var results = document.getElementById("results")
|
||||
results.innerHTML = "Searching..."
|
||||
e.preventDefault()
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_admin_search",
|
||||
args: document.getElementById("args").value,
|
||||
posts_per_page: document.getElementById("posts_per_page").value,
|
||||
post_types: document.getElementById("post_types").value,
|
||||
s: document.getElementById("s").value,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
results.innerHTML = response
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
// Show the filters on the "Admin search" page.
|
||||
$(document).on("click", "#show_filters", function (e) {
|
||||
$("#relevanssi_filter_list").toggle()
|
||||
$("#show_filters").toggle()
|
||||
$("#hide_filters").toggle()
|
||||
})
|
||||
|
||||
// Hide the filters on the "Admin search" page.
|
||||
$(document).on("click", "#hide_filters", function (e) {
|
||||
$("#relevanssi_filter_list").toggle()
|
||||
$("#show_filters").toggle()
|
||||
$("#hide_filters").toggle()
|
||||
})
|
||||
|
||||
$(document).on("click", "#next_page", function (e) {
|
||||
e.preventDefault()
|
||||
var results = document.getElementById("results")
|
||||
var offset = parseInt(document.getElementById("offset").innerHTML)
|
||||
var posts = parseInt(document.getElementById("posts_per_page").value)
|
||||
results.innerHTML = "Searching..."
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_admin_search",
|
||||
args: document.getElementById("args").value,
|
||||
posts_per_page: posts,
|
||||
s: document.getElementById("s").value,
|
||||
offset: offset,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
results.innerHTML = response
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
$(document).on("click", "#prev_page", function (e) {
|
||||
e.preventDefault()
|
||||
var results = document.getElementById("results")
|
||||
var offset = parseInt(document.getElementById("offset").innerHTML)
|
||||
var posts = parseInt(document.getElementById("posts_per_page").value)
|
||||
offset = offset - posts - posts
|
||||
if (offset < 0) offset = 0
|
||||
results.innerHTML = "Searching..."
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_admin_search",
|
||||
args: document.getElementById("args").value,
|
||||
posts_per_page: document.getElementById("posts_per_page").value,
|
||||
s: document.getElementById("s").value,
|
||||
offset: offset,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
results.innerHTML = response
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
$(document).on("click", ".pin", function (e) {
|
||||
e.preventDefault()
|
||||
var keyword = e.target.dataset.keyword
|
||||
var post_id = e.target.dataset.postid
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_pin_post",
|
||||
keyword,
|
||||
post_id,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
var results = document.getElementById("results")
|
||||
results.innerHTML = "Searching..."
|
||||
e.preventDefault()
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_admin_search",
|
||||
args: document.getElementById("args").value,
|
||||
posts_per_page: document.getElementById("posts_per_page").value,
|
||||
s: document.getElementById("s").value,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
results.innerHTML = response
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
$(document).on("click", ".unpin", function (e) {
|
||||
e.preventDefault()
|
||||
var keyword = e.target.dataset.keyword
|
||||
var post_id = e.target.dataset.postid
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_unpin_post",
|
||||
keyword,
|
||||
post_id,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
var results = document.getElementById("results")
|
||||
results.innerHTML = "Searching..."
|
||||
e.preventDefault()
|
||||
jQuery.ajax({
|
||||
type: "POST",
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: "relevanssi_admin_search",
|
||||
args: document.getElementById("args").value,
|
||||
posts_per_page: document.getElementById("posts_per_page").value,
|
||||
s: document.getElementById("s").value,
|
||||
security: nonce.searching_nonce,
|
||||
},
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
results.innerHTML = response
|
||||
},
|
||||
})
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,53 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
$("#build_index").click(function () {
|
||||
$("#relevanssi-progress").show()
|
||||
$("#results").show()
|
||||
$("#relevanssi-timer").show()
|
||||
$("#relevanssi-indexing-instructions").show()
|
||||
$("#stateoftheindex").html(relevanssi.reload_state)
|
||||
$("#indexing_button_instructions").hide()
|
||||
var results = document.getElementById("results")
|
||||
results.value = ""
|
||||
|
||||
var data = {
|
||||
action: "relevanssi_truncate_index",
|
||||
security: nonce.indexing_nonce,
|
||||
}
|
||||
|
||||
intervalID = window.setInterval(relevanssiUpdateClock, 1000)
|
||||
|
||||
console.log("Truncating index.")
|
||||
results.value += relevanssi.truncating_index + " "
|
||||
jQuery.post(ajaxurl, data, function (response) {
|
||||
truncate_response = JSON.parse(response)
|
||||
console.log("Truncate index: " + truncate_response)
|
||||
if (truncate_response == true) {
|
||||
results.value += relevanssi.done + "\n"
|
||||
}
|
||||
|
||||
var data = {
|
||||
action: "relevanssi_count_posts",
|
||||
}
|
||||
console.log("Counting posts.")
|
||||
results.value += relevanssi.counting_posts + " "
|
||||
jQuery.post(ajaxurl, data, function (response) {
|
||||
count_response = JSON.parse(response)
|
||||
console.log("Counted " + count_response + " posts.")
|
||||
var post_total = parseInt(count_response)
|
||||
results.value += count_response + " " + relevanssi.posts_found + "\n"
|
||||
|
||||
var args = {
|
||||
completed: 0,
|
||||
total: post_total,
|
||||
offset: 0,
|
||||
total_seconds: 0,
|
||||
limit: relevanssi_params.indexing_limit,
|
||||
adjust: relevanssi_params.indexing_adjust,
|
||||
extend: false,
|
||||
security: nonce.indexing_nonce,
|
||||
}
|
||||
process_indexing_step(args)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
118
wp/wp-content/plugins/relevanssi-premium/lib/admin_styles.css
Normal file
118
wp/wp-content/plugins/relevanssi-premium/lib/admin_styles.css
Normal file
@@ -0,0 +1,118 @@
|
||||
p.important {
|
||||
color: #992000;
|
||||
}
|
||||
|
||||
table.form-table table.widefat th {
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
#relevanssi_min_word_length {
|
||||
width: 3em;
|
||||
}
|
||||
|
||||
#relevanssi_trim_logs, #relevanssi_trim_click_logs {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
#index_field_input {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
#indexing_tab #results {
|
||||
display: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#relevanssi-progress {
|
||||
display: none;
|
||||
margin-bottom: 2em;
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.rpi-indicator {
|
||||
width: 0;
|
||||
height: 20px;
|
||||
background-color: #afe240;
|
||||
}
|
||||
|
||||
.relevanssi-weights-table {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.relevanssi-weights-table td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.relevanssi-weights-table td.col-2, .relevanssi-weights-table th.col-2 {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.rpi-progress {
|
||||
display: none;
|
||||
margin: 0.5em 0 2em 0;
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.rpi-progress div {
|
||||
width: 0;
|
||||
height: 20px;
|
||||
background-color: #afe240;
|
||||
}
|
||||
|
||||
#relevanssi_results {
|
||||
display: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#relevanssi_show_pdf_errors {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
color: #0073aa;
|
||||
}
|
||||
|
||||
#relevanssi_pdf_errors {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.visually_hidden {
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
clip: rect(0,0,0,0);
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.relevanssi_disabled, .relevanssi_disabled td, .relevanssi_disabled th, .relevanssi_disabled p {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
#relevanssi-timer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#category_inclusion_checklist ul.children, #category_exclusion_checklist ul.children {
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
#relevanssi_filter_list {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#redirect_table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#relevanssi_sees_container, #relevanssi_db_view_container {
|
||||
width: 80%;
|
||||
background: white;
|
||||
padding: 5px 20px;
|
||||
border: thin solid black;
|
||||
overflow: scroll;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/class-relevanssi-taxonomy-walker.php
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
/**
|
||||
* A taxonomy walker used in Relevanssi interface.
|
||||
*
|
||||
* This is needed for wp_terms_checklist() in the Relevanssi admin interface to
|
||||
* control the way the taxonomies are listed.
|
||||
*/
|
||||
class Relevanssi_Taxonomy_Walker extends Walker_Category_Checklist {
|
||||
/**
|
||||
* Name of the input element.
|
||||
*
|
||||
* @var string $name Name of the input element.
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Creates a single element of the list.
|
||||
*
|
||||
* @see Walker::start_el()
|
||||
*
|
||||
* @param string $output Used to append additional content (passed by reference).
|
||||
* @param object $category Category data object.
|
||||
* @param int $depth Optional. Depth of category in reference to parents. Default 0.
|
||||
* @param array $args Optional. An array of arguments. See wp_list_categories(). Default empty array.
|
||||
* @param int $id Optional. ID of the current category. Default 0.
|
||||
*/
|
||||
public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
|
||||
if ( empty( $args['taxonomy'] ) ) {
|
||||
$taxonomy = 'category';
|
||||
} else {
|
||||
$taxonomy = $args['taxonomy'];
|
||||
}
|
||||
|
||||
$name = $this->name;
|
||||
|
||||
if ( ! isset( $args['popular_cats'] ) ) {
|
||||
$args['popular_cats'] = array();
|
||||
}
|
||||
|
||||
if ( ! isset( $args['selected_cats'] ) ) {
|
||||
$args['selected_cats'] = array();
|
||||
}
|
||||
|
||||
$class = '';
|
||||
$inner_class = '';
|
||||
|
||||
if ( ! empty( $args['list_only'] ) ) {
|
||||
$aria_checked = 'false';
|
||||
$inner_class = 'category';
|
||||
|
||||
$output .= "\n" . '<li' . $class . '>' .
|
||||
'<div class="' . $inner_class . '" data-term-id=' . $category->term_id .
|
||||
' tabindex="0" role="checkbox" aria-checked="' . $aria_checked . '">' .
|
||||
/** This filter is documented in wp-includes/category-template.php */
|
||||
esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</div>';
|
||||
} else {
|
||||
$output .= "\n<li id='{$taxonomy}-{$category->term_id}'$class>" .
|
||||
'<label class="selectit"><input value="' . $category->term_id . '" type="checkbox" name="' . $name . '[]" id="in-' . $taxonomy . '-' . $category->term_id . '"' .
|
||||
checked( in_array( intval( $category->term_id ), $args['selected_cats'], true ), true, false ) .
|
||||
disabled( empty( $args['disabled'] ), false, false ) . ' /> ' .
|
||||
/** This filter is documented in wp-includes/category-template.php */
|
||||
esc_html( apply_filters( 'the_category', $category->name, '', '' ) ) . '</label>';
|
||||
}
|
||||
}
|
||||
}
|
||||
1937
wp/wp-content/plugins/relevanssi-premium/lib/common.php
Normal file
1937
wp/wp-content/plugins/relevanssi-premium/lib/common.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/acf.php
|
||||
*
|
||||
* Advanced Custom Fields compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_action( 'acf/render_field_settings', 'relevanssi_acf_exclude_setting' );
|
||||
add_filter( 'relevanssi_search_ok', 'relevanssi_acf_relationship_fields' );
|
||||
add_filter( 'relevanssi_index_custom_fields', 'relevanssi_acf_exclude_fields', 10, 2 );
|
||||
|
||||
/**
|
||||
* Disables Relevanssi in the ACF Relationship field post search.
|
||||
*
|
||||
* We don't want to use Relevanssi on the ACF Relationship field post searches, so
|
||||
* this function disables it (on the 'relevanssi_search_ok' hook).
|
||||
*
|
||||
* @param boolean $search_ok Block the search or not.
|
||||
*
|
||||
* @return boolean False, if this is an ACF Relationship field search, pass the
|
||||
* parameter unchanged otherwise.
|
||||
*/
|
||||
function relevanssi_acf_relationship_fields( $search_ok ) {
|
||||
// phpcs:disable WordPress.Security.NonceVerification
|
||||
if ( isset( $_REQUEST['action'] )
|
||||
&& is_string( $_REQUEST['action'] )
|
||||
&& 'acf' === substr( $_REQUEST['action'], 0, 3 ) ) {
|
||||
$search_ok = false;
|
||||
}
|
||||
return $search_ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes the human-readable value of "choice" options list from ACF.
|
||||
*
|
||||
* @author Droz Raphaël
|
||||
*
|
||||
* @param array $insert_data The insert data array.
|
||||
* @param int $post_id The post ID.
|
||||
* @param string $field_name Name of the field.
|
||||
* @param string $field_value The field value.
|
||||
*
|
||||
* @return int Number of tokens indexed.
|
||||
*/
|
||||
function relevanssi_index_acf( &$insert_data, $post_id, $field_name, $field_value ) {
|
||||
if ( ! is_admin() ) {
|
||||
include_once ABSPATH . 'wp-admin/includes/plugin.php'; // Otherwise is_plugin_active() will cause a fatal error.
|
||||
}
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
return 0;
|
||||
}
|
||||
if ( ! is_plugin_active( 'advanced-custom-fields/acf.php' ) && ! is_plugin_active( 'advanced-custom-fields-pro/acf.php' ) ) {
|
||||
return 0;
|
||||
}
|
||||
if ( ! function_exists( 'get_field_object' ) ) {
|
||||
return 0; // ACF is active, but not loaded.
|
||||
}
|
||||
|
||||
$field_object = get_field_object( $field_name, $post_id );
|
||||
if ( ! isset( $field_object['choices'] ) ) {
|
||||
return 0; // Not a "select" field.
|
||||
}
|
||||
if ( is_array( $field_value ) ) {
|
||||
return 0; // Not handled (currently).
|
||||
}
|
||||
if ( ! isset( $field_object['choices'][ $field_value ] ) ) {
|
||||
return 0; // Value does not exist.
|
||||
}
|
||||
|
||||
$n = 0;
|
||||
|
||||
/**
|
||||
* Filters the field value before it is used to save the insert data.
|
||||
*
|
||||
* The value is used as an array key, so it needs to be an integer or a
|
||||
* string. If your custom field values are arrays or objects, use this
|
||||
* filter hook to convert them into strings.
|
||||
*
|
||||
* @param mixed $field_content The ACF field value.
|
||||
* @param string $field_name The ACF field name.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return string|int The field value.
|
||||
*/
|
||||
$value = apply_filters(
|
||||
'relevanssi_acf_field_value',
|
||||
$field_object['choices'][ $field_value ],
|
||||
$field_name,
|
||||
$post_id
|
||||
);
|
||||
|
||||
if ( $value && ( is_integer( $value ) || is_string( $value ) ) ) {
|
||||
$min_word_length = get_option( 'relevanssi_min_word_length', 3 );
|
||||
|
||||
/** This filter is documented in lib/indexing.php */
|
||||
$value_tokens = apply_filters( 'relevanssi_indexing_tokens', relevanssi_tokenize( $value, true, $min_word_length, 'indexing' ), 'custom_field' );
|
||||
foreach ( $value_tokens as $token => $count ) {
|
||||
++$n;
|
||||
if ( ! isset( $insert_data[ $token ]['customfield'] ) ) {
|
||||
$insert_data[ $token ]['customfield'] = 0;
|
||||
}
|
||||
$insert_data[ $token ]['customfield'] += $count;
|
||||
|
||||
// Premium indexes more detail about custom fields.
|
||||
if ( function_exists( 'relevanssi_customfield_detail' ) ) {
|
||||
$insert_data = relevanssi_customfield_detail( $insert_data, $token, $count, $field_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Relevanssi exclude setting to ACF fields.
|
||||
*
|
||||
* @param array $field The field object array.
|
||||
*/
|
||||
function relevanssi_acf_exclude_setting( $field ) {
|
||||
if ( ! function_exists( 'acf_render_field_setting' ) ) {
|
||||
return;
|
||||
}
|
||||
if ( 'clone' === $field['type'] ) {
|
||||
return;
|
||||
}
|
||||
acf_render_field_setting(
|
||||
$field,
|
||||
array(
|
||||
'label' => __( 'Exclude from Relevanssi index', 'relevanssi' ),
|
||||
'instructions' => __( 'If this setting is enabled, Relevanssi will not index the value of this field for posts.', 'relevanssi' ),
|
||||
'name' => 'relevanssi_exclude',
|
||||
'type' => 'true_false',
|
||||
'ui' => 1,
|
||||
),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes ACF fields based on the exclude setting.
|
||||
*
|
||||
* Hooks on to relevanssi_index_custom_fields.
|
||||
*
|
||||
* @param array $fields The list of custom fields to index.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return array Filtered list of custom fields.
|
||||
*/
|
||||
function relevanssi_acf_exclude_fields( $fields, $post_id ) {
|
||||
$included_fields = array();
|
||||
$excluded_fields = array();
|
||||
|
||||
/**
|
||||
* Filters the types of ACF fields to exclude from indexing.
|
||||
*
|
||||
* By default, blocks 'repeater', 'flexible_content' and 'group' are
|
||||
* excluded from Relevanssi indexing. You can add other field types here.
|
||||
*
|
||||
* @param array $excluded_field_types The field types to exclude.
|
||||
*/
|
||||
$blocked_field_types = apply_filters(
|
||||
'relevanssi_blocked_field_types',
|
||||
array( 'repeater', 'flexible_content', 'group' )
|
||||
);
|
||||
|
||||
global $post;
|
||||
foreach ( $fields as $field ) {
|
||||
$global_post = $post; // ACF fields can change the global $post.
|
||||
$field_object = get_field_object( $field );
|
||||
$post = $global_post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
|
||||
if ( ! $field_object || ! is_array( $field_object ) ) {
|
||||
$field_id = relevanssi_acf_get_field_id( $field, $post_id );
|
||||
if ( ! $field_id ) {
|
||||
// No field ID -> not an ACF field. Include.
|
||||
$included_fields[] = $field;
|
||||
} else {
|
||||
/*
|
||||
* This field has a field ID, but get_field_object() does not
|
||||
* return a field object. This may be a clone field, in which
|
||||
* case we can try to get the field object from the field ID.
|
||||
* Clone fields have keys like field_xxx_field_yyy, where the
|
||||
* field_yyy is the part we need.
|
||||
*/
|
||||
$field_id = preg_replace( '/.*_(field_.*)/', '$1', $field_id );
|
||||
$field_object = get_field_object( $field_id );
|
||||
}
|
||||
}
|
||||
if ( $field_object ) {
|
||||
/**
|
||||
* Filters the ACF field object.
|
||||
*
|
||||
* If the filter returns a false value, Relevanssi will not index
|
||||
* the field.
|
||||
*
|
||||
* @param array $field_object The field object.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return array The filtered field object.
|
||||
*/
|
||||
$field_object = apply_filters(
|
||||
'relevanssi_acf_field_object',
|
||||
$field_object,
|
||||
$post_id
|
||||
);
|
||||
|
||||
if ( ! $field_object ) {
|
||||
continue;
|
||||
}
|
||||
if ( isset( $field_object['relevanssi_exclude'] ) && 1 === $field_object['relevanssi_exclude'] ) {
|
||||
continue;
|
||||
}
|
||||
if ( relevanssi_acf_is_parent_excluded( $field_object ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( isset( $field_object['type'] ) && in_array( $field_object['type'], $blocked_field_types, true ) ) {
|
||||
continue;
|
||||
}
|
||||
$included_fields[] = $field;
|
||||
}
|
||||
}
|
||||
return $included_fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the field has an excluded parent field.
|
||||
*
|
||||
* If the field has a "parent" value set, this function gets the parent field
|
||||
* post based on the post ID in the "parent" value. This is done recursively
|
||||
* until we reach the top or find an excluded parent.
|
||||
*
|
||||
* @param array $field_object The field object.
|
||||
*
|
||||
* @return bool Returns true if the post has an excluded parent.
|
||||
*/
|
||||
function relevanssi_acf_is_parent_excluded( $field_object ) {
|
||||
if ( isset( $field_object['parent'] ) ) {
|
||||
$parent = $field_object['parent'];
|
||||
if ( $parent ) {
|
||||
$parent_field_post = get_post( $parent );
|
||||
if ( $parent_field_post ) {
|
||||
$parent_object = get_field_object( $parent_field_post->post_name );
|
||||
if ( $parent_object ) {
|
||||
if ( isset( $parent_object['relevanssi_exclude'] ) && 1 === $parent_object['relevanssi_exclude'] ) {
|
||||
return true;
|
||||
}
|
||||
return relevanssi_acf_is_parent_excluded( $parent_object );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field ID from the field name.
|
||||
*
|
||||
* The field ID is stored in the postmeta table with the field name prefixed
|
||||
* with an underscore as the key.
|
||||
*
|
||||
* @param string $field_name The field name.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return string The field ID.
|
||||
*/
|
||||
function relevanssi_acf_get_field_id( $field_name, $post_id ) {
|
||||
global $wpdb;
|
||||
|
||||
$field_id = $wpdb->get_var(
|
||||
$wpdb->prepare(
|
||||
"SELECT meta_value FROM $wpdb->postmeta
|
||||
WHERE post_id = %d
|
||||
AND meta_key = %s",
|
||||
$post_id,
|
||||
'_' . $field_name
|
||||
)
|
||||
);
|
||||
return $field_id;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/aioseo.php
|
||||
*
|
||||
* All-in-One SEO noindex filtering function.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_do_not_index', 'relevanssi_aioseo_noindex', 10, 2 );
|
||||
add_filter( 'relevanssi_indexing_restriction', 'relevanssi_aioseo_exclude' );
|
||||
add_action( 'relevanssi_indexing_tab_advanced', 'relevanssi_aioseo_form', 20 );
|
||||
add_action( 'relevanssi_indexing_options', 'relevanssi_aioseo_options' );
|
||||
|
||||
/**
|
||||
* Blocks indexing of posts marked "noindex" in the All-in-One SEO settings.
|
||||
*
|
||||
* Attaches to the 'relevanssi_do_not_index' filter hook.
|
||||
*
|
||||
* @param boolean $do_not_index True, if the post shouldn't be indexed.
|
||||
* @param integer $post_id The post ID number.
|
||||
*
|
||||
* @return string|boolean If the post shouldn't be indexed, this returns
|
||||
* 'aioseo_seo'. The value may also be a boolean.
|
||||
*/
|
||||
function relevanssi_aioseo_noindex( bool $do_not_index, int $post_id ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $do_not_index;
|
||||
}
|
||||
$noindex_posts = relevanssi_aioseo_get_noindex_posts();
|
||||
if ( in_array( $post_id, $noindex_posts, true ) ) {
|
||||
$do_not_index = 'All-in-One SEO';
|
||||
}
|
||||
return $do_not_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes the "noindex" posts from Relevanssi indexing.
|
||||
*
|
||||
* Adds a MySQL query restriction that blocks posts that have the aioseo SEO
|
||||
* "noindex" setting set to "1" from indexing.
|
||||
*
|
||||
* @param array $restriction An array with two values: 'mysql' for the MySQL
|
||||
* query restriction to modify, 'reason' for the reason of restriction.
|
||||
*/
|
||||
function relevanssi_aioseo_exclude( array $restriction ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$restriction['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM
|
||||
{$wpdb->prefix}aioseo_posts WHERE robots_noindex = '1' ) ";
|
||||
$restriction['reason'] .= ' All-in-One SEO';
|
||||
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the post IDs where robots_noindex is set to 1 in the aioseo_posts
|
||||
* table.
|
||||
*
|
||||
* @return array An array of post IDs.
|
||||
*/
|
||||
function relevanssi_aioseo_get_noindex_posts() {
|
||||
global $wpdb, $relevanssi_aioseo_noindex_cache;
|
||||
if ( ! empty( $relevanssi_aioseo_noindex_cache ) ) {
|
||||
return $relevanssi_aioseo_noindex_cache;
|
||||
}
|
||||
$relevanssi_aioseo_noindex_cache = $wpdb->get_col( "SELECT post_id FROM {$wpdb->prefix}aioseo_posts WHERE 'robots_noindex' = '1'" );
|
||||
return $relevanssi_aioseo_noindex_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the form fields for disabling the feature.
|
||||
*/
|
||||
function relevanssi_aioseo_form() {
|
||||
$seo_noindex = get_option( 'relevanssi_seo_noindex' );
|
||||
$seo_noindex = relevanssi_check( $seo_noindex );
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for='relevanssi_seo_noindex'><?php esc_html_e( 'Use All-in-One SEO noindex', 'relevanssi' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<label for='relevanssi_seo_noindex'>
|
||||
<input type='checkbox' name='relevanssi_seo_noindex' id='relevanssi_seo_noindex' <?php echo esc_attr( $seo_noindex ); ?> />
|
||||
<?php esc_html_e( 'Use All-in-One SEO noindex.', 'relevanssi' ); ?>
|
||||
</label>
|
||||
<p class="description"><?php esc_html_e( 'If checked, Relevanssi will not index posts marked as "No index" in All-in-One SEO settings.', 'relevanssi' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the SEO No index option.
|
||||
*
|
||||
* @param array $request An array of option values from the request.
|
||||
*/
|
||||
function relevanssi_aioseo_options( array $request ) {
|
||||
relevanssi_update_off_or_on( $request, 'relevanssi_seo_noindex', true );
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/avada.php
|
||||
*
|
||||
* Avada theme compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter(
|
||||
'fusion_live_search_query_args',
|
||||
function ( $args ) {
|
||||
$args['relevanssi'] = true;
|
||||
return $args;
|
||||
}
|
||||
);
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/bricks.php
|
||||
*
|
||||
* Bricks theme compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'bricks/posts/query_vars', 'relevanssi_bricks_enable', 10 );
|
||||
add_filter( 'relevanssi_custom_field_value', 'relevanssi_bricks_values', 10, 2 );
|
||||
add_filter( 'relevanssi_index_custom_fields', 'relevanssi_add_bricks' );
|
||||
add_filter( 'option_relevanssi_index_fields', 'relevanssi_bricks_fix_none_setting' );
|
||||
add_action( 'save_post', 'relevanssi_insert_edit', 99, 1 );
|
||||
|
||||
/**
|
||||
* Enables Relevanssi in the query when the 's' query var is set.
|
||||
*
|
||||
* @param array $query_vars The query variables.
|
||||
*
|
||||
* @return array The query variables with the Relevanssi toggle enabled.
|
||||
*/
|
||||
function relevanssi_bricks_enable( $query_vars ) {
|
||||
if ( isset( $query_vars['s'] ) ) {
|
||||
$query_vars['relevanssi'] = true;
|
||||
}
|
||||
return $query_vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the `_bricks_page_content_2` to the list of indexed custom fields.
|
||||
*
|
||||
* @param array|boolean $fields An array of custom fields to index, or false.
|
||||
*
|
||||
* @return array An array of custom fields, including `_bricks_page_content_2`.
|
||||
*/
|
||||
function relevanssi_add_bricks( $fields ) {
|
||||
if ( ! is_array( $fields ) ) {
|
||||
$fields = array();
|
||||
}
|
||||
if ( ! in_array( '_bricks_page_content_2', $fields, true ) ) {
|
||||
$fields[] = '_bricks_page_content_2';
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes only text from _bricks_page_content_2 custom field.
|
||||
*
|
||||
* This function goes through the multilevel array of _bricks_page_content_2
|
||||
* and only picks up the "text" elements inside it, discarding everything else.
|
||||
*
|
||||
* @param array $value An array of custom field values.
|
||||
* @param string $field The name of the custom field.
|
||||
*
|
||||
* @return array An array containing a string with all the values concatenated
|
||||
* together.
|
||||
*/
|
||||
function relevanssi_bricks_values( $value, $field ) {
|
||||
if ( '_bricks_page_content_2' !== $field ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$content = '';
|
||||
array_walk_recursive(
|
||||
$value,
|
||||
function ( $text, $key ) use ( &$content ) {
|
||||
if ( 'text' === $key ) {
|
||||
$content .= ' ' . $text;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return array( $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the Bricks builder shortcode is included in the index, even when
|
||||
* the custom field setting is set to 'none'.
|
||||
*
|
||||
* @param string $value The custom field indexing setting value. The parameter
|
||||
* is ignored, Relevanssi disables this filter and then checks the option to
|
||||
* see what the value is.
|
||||
*
|
||||
* @return string If value is undefined, it's set to '_bricks_page_content_2'.
|
||||
*/
|
||||
function relevanssi_bricks_fix_none_setting( $value ) {
|
||||
if ( ! $value ) {
|
||||
$value = '_bricks_page_content_2';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/elementor.php
|
||||
*
|
||||
* Elementor page builder compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_search_ok', 'relevanssi_block_elementor_library', 10, 2 );
|
||||
|
||||
/**
|
||||
* Blocks Relevanssi from interfering with the Elementor Library searches.
|
||||
*
|
||||
* @param bool $ok Should Relevanssi be allowed to process the query.
|
||||
* @param WP_Query $query The WP_Query object.
|
||||
*
|
||||
* @return bool Returns false, if this is an Elementor library search.
|
||||
*/
|
||||
function relevanssi_block_elementor_library( bool $ok, WP_Query $query ): bool {
|
||||
if ( 'elementor_library' === $query->query_vars['post_type'] ) {
|
||||
$ok = false;
|
||||
}
|
||||
return $ok;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/fibosearch.php
|
||||
*
|
||||
* Fibo Search compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'dgwt/wcas/search_query/args', 'relevanssi_enable_relevanssi_in_fibo' );
|
||||
|
||||
/**
|
||||
* Adds the 'relevanssi' parameter to the Fibo Search.
|
||||
*
|
||||
* Uses the dgwt/wcas/search_query_args filter hook to modify the search query.
|
||||
*
|
||||
* @param array $args The search arguments.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function relevanssi_enable_relevanssi_in_fibo( $args ) {
|
||||
$args['relevanssi'] = true;
|
||||
return $args;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/groups.php
|
||||
*
|
||||
* Groups compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_ok', 'relevanssi_groups_compatibility', 10, 2 );
|
||||
|
||||
/**
|
||||
* Checks whether the user is allowed to see the post.
|
||||
*
|
||||
* Only applies to published posts.
|
||||
*
|
||||
* @param boolean $post_ok Can the post be shown to the user.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return boolean $post_ok True if the user is allowed to see the post,
|
||||
* otherwise false.
|
||||
*/
|
||||
function relevanssi_groups_compatibility( $post_ok, $post_id ) {
|
||||
$status = relevanssi_get_post_status( $post_id );
|
||||
|
||||
if ( 'publish' === $status ) {
|
||||
// Only apply to published posts, don't apply to drafts.
|
||||
$current_user = wp_get_current_user();
|
||||
$post_ok = Groups_Post_Access::user_can_read_post( $post_id, $current_user->ID );
|
||||
}
|
||||
|
||||
return $post_ok;
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/gutenberg.php
|
||||
*
|
||||
* Gutenberg compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_content', 'relevanssi_gutenberg_block_rendering', 10, 2 );
|
||||
|
||||
/**
|
||||
* Registers rest_after_insert_{post_type} actions for all indexed post types.
|
||||
*
|
||||
* Runs on `admin_init` action hook and registers the function
|
||||
* `relevanssi_save_gutenberg_postdata` for all indexed post types.
|
||||
*
|
||||
* @see relevanssi_save_gutenberg_postdata
|
||||
*/
|
||||
function relevanssi_register_gutenberg_actions() {
|
||||
if ( ! RELEVANSSI_PREMIUM ) {
|
||||
return;
|
||||
}
|
||||
$index_post_types = get_option( 'relevanssi_index_post_types', array() );
|
||||
array_walk(
|
||||
$index_post_types,
|
||||
function ( $post_type ) {
|
||||
if ( 'bogus' !== $post_type ) {
|
||||
add_action(
|
||||
'rest_after_insert_' . $post_type,
|
||||
'relevanssi_save_gutenberg_postdata'
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders Gutenberg blocks.
|
||||
*
|
||||
* Renders all sorts of Gutenberg blocks, including reusable blocks and ACF
|
||||
* blocks. Also enables basic Gutenberg deindexing: you can add an extra CSS
|
||||
* class 'relevanssi_noindex' to a block to stop it from being indexed by
|
||||
* Relevanssi. This function is essentially the same as core do_blocks().
|
||||
*
|
||||
* @see do_blocks()
|
||||
*
|
||||
* @param string $content The post content.
|
||||
* @param object $post_object The post object.
|
||||
*
|
||||
* @return string The post content with the rendered content added.
|
||||
*/
|
||||
function relevanssi_gutenberg_block_rendering( $content, $post_object ) {
|
||||
/**
|
||||
* Filters whether the blocks are rendered or not.
|
||||
*
|
||||
* If this filter returns false, the blocks in this post are not rendered,
|
||||
* and the post content is returned as such.
|
||||
*
|
||||
* @param boolean If true, render the blocks. Default true.
|
||||
* @param object The post object.
|
||||
*/
|
||||
if ( ! apply_filters( 'relevanssi_render_blocks', true, $post_object ) ) {
|
||||
return $content;
|
||||
}
|
||||
$blocks = parse_blocks( $content );
|
||||
$output = '';
|
||||
|
||||
foreach ( $blocks as $block ) {
|
||||
/**
|
||||
* Filters the Gutenberg block before it is rendered.
|
||||
*
|
||||
* If the block is non-empty after the filter and it's className
|
||||
* parameter is not 'relevanssi_noindex', it will be passed on to the
|
||||
* render_block() function for rendering.
|
||||
*
|
||||
* @see render_block
|
||||
*
|
||||
* @param array $block The Gutenberg block element.
|
||||
*/
|
||||
$block = apply_filters( 'relevanssi_block_to_render', $block );
|
||||
|
||||
if ( ! $block ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $block['attrs']['className'] )
|
||||
&& false !== strstr( $block['attrs']['className'], 'relevanssi_noindex' )
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$block = relevanssi_process_inner_blocks( $block );
|
||||
|
||||
/**
|
||||
* Filters the Gutenberg block after it is rendered.
|
||||
*
|
||||
* The value is the output from render_block( $block ). Feel free to
|
||||
* modify it as you wish.
|
||||
*
|
||||
* @see render_block
|
||||
*
|
||||
* @param string The rendered block content.
|
||||
* @param array $block The Gutenberg block being rendered.
|
||||
*
|
||||
* @return string The filtered block content.
|
||||
*/
|
||||
$output .= apply_filters( 'relevanssi_rendered_block', render_block( $block ), $block );
|
||||
|
||||
}
|
||||
|
||||
// If there are blocks in this content, we shouldn't run wpautop() on it later.
|
||||
$priority = has_filter( 'the_content', 'wpautop' );
|
||||
if ( false !== $priority && doing_filter( 'the_content' ) && has_blocks( $content ) ) {
|
||||
remove_filter( 'the_content', 'wpautop', $priority );
|
||||
add_filter( 'the_content', '_restore_wpautop_hook', $priority + 1 );
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs recursively through inner blocks to filter them.
|
||||
*
|
||||
* Runs relevanssi_block_to_render and the relevanssi_noindex CSS class check
|
||||
* on all inner blocks. If inner blocks are filtered out, they will be removed
|
||||
* with empty blocks of the type "core/fake". Removing the inner blocks causes
|
||||
* problems; that's why they are replaced. The blocks are rendered here;
|
||||
* everything will be rendered once at the top level.
|
||||
*
|
||||
* @param array $block A Gutenberg block.
|
||||
*
|
||||
* @return array The filtered block.
|
||||
*/
|
||||
function relevanssi_process_inner_blocks( $block ) {
|
||||
$innerblocks_to_keep = array();
|
||||
|
||||
$empty_block = array(
|
||||
'blockName' => 'core/fake',
|
||||
'attrs' => array(),
|
||||
'innerHTML' => '',
|
||||
'innerBlocks' => array(),
|
||||
);
|
||||
|
||||
foreach ( $block['innerBlocks'] as $inner_block ) {
|
||||
/* Filter documented in /lib/compatibility/gutenberg.php. */
|
||||
$inner_block = apply_filters( 'relevanssi_block_to_render', $inner_block );
|
||||
|
||||
if ( ! $inner_block ) {
|
||||
$innerblocks_to_keep[] = $empty_block;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( $inner_block['attrs']['className'] )
|
||||
&& false !== strstr( $inner_block['attrs']['className'], 'relevanssi_noindex' )
|
||||
) {
|
||||
$innerblocks_to_keep[] = $empty_block;
|
||||
continue;
|
||||
}
|
||||
|
||||
$inner_block = relevanssi_process_inner_blocks( $inner_block );
|
||||
|
||||
$innerblocks_to_keep[] = $inner_block;
|
||||
}
|
||||
|
||||
$block['innerBlocks'] = $innerblocks_to_keep;
|
||||
return $block;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/jetsmartfilters.php
|
||||
*
|
||||
* JetSmartFilters compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_action( 'pre_get_posts', 'relevanssi_jetsmartfilters', 9999 );
|
||||
|
||||
/**
|
||||
* Makes JetSmartFilters use posts from Relevanssi.
|
||||
*
|
||||
* @param WP_Query $wp_query The wp_query object.
|
||||
*/
|
||||
function relevanssi_jetsmartfilters( $wp_query ) {
|
||||
if (
|
||||
! isset( $wp_query->query['jet_smart_filters'] )
|
||||
|| empty( $wp_query->query['s'] )
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
's' => $wp_query->query['s'],
|
||||
'fields' => 'ids',
|
||||
'posts_per_page' => -1,
|
||||
'relevanssi' => true,
|
||||
);
|
||||
|
||||
$relevanssi_query = new WP_Query( $args );
|
||||
|
||||
$results = ! empty( $relevanssi_query->posts )
|
||||
? $relevanssi_query->posts
|
||||
: array( 0 );
|
||||
|
||||
$wp_query->set( 'post__in', $results );
|
||||
$wp_query->set( 'post_type', 'any' );
|
||||
$wp_query->set( 'post_status', 'any' );
|
||||
$wp_query->set( 'orderby', 'post__in' );
|
||||
$wp_query->set( 'order', 'DESC' );
|
||||
$wp_query->set( 's', false );
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/memberpress.php
|
||||
*
|
||||
* Memberpress compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_ok', 'relevanssi_memberpress_compatibility', 10, 2 );
|
||||
|
||||
/**
|
||||
* Checks whether the user is allowed to see the post.
|
||||
*
|
||||
* @param boolean $post_ok Can the post be shown to the user.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return boolean $post_ok True if the user is allowed to see the post,
|
||||
* otherwise false.
|
||||
*/
|
||||
function relevanssi_memberpress_compatibility( $post_ok, $post_id ) {
|
||||
$post = get_post( $post_id );
|
||||
if ( MeprRule::is_locked( $post ) ) {
|
||||
$post_ok = false;
|
||||
}
|
||||
|
||||
return $post_ok;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/members.php
|
||||
*
|
||||
* Members compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_ok', 'relevanssi_members_compatibility', 10, 2 );
|
||||
|
||||
/**
|
||||
* Checks whether the user is allowed to see the post.
|
||||
*
|
||||
* Only applies to private posts and only if the "content permissions" feature
|
||||
* is enabled.
|
||||
*
|
||||
* @param boolean $post_ok Can the post be shown to the user.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return boolean $post_ok True if the user is allowed to see the post,
|
||||
* otherwise false.
|
||||
*/
|
||||
function relevanssi_members_compatibility( $post_ok, $post_id ) {
|
||||
$status = relevanssi_get_post_status( $post_id );
|
||||
|
||||
if ( 'private' === $status ) {
|
||||
if ( members_content_permissions_enabled() ) {
|
||||
$post_ok = members_can_current_user_view_post( $post_id );
|
||||
}
|
||||
}
|
||||
|
||||
return $post_ok;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/ninjatables.php
|
||||
*
|
||||
* Ninja Tables compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_content', 'relevanssi_index_ninja_tables' );
|
||||
|
||||
/**
|
||||
* Indexes Ninja Tables table contents.
|
||||
*
|
||||
* Uses regular expression matching to find all the Ninja Tables shortcodes in
|
||||
* the post content and then uses relevanssi_index_ninja_table() to convert the
|
||||
* tables into strings.
|
||||
*
|
||||
* @uses $wpdb WordPress database abstraction.
|
||||
* @see relevanssi_index_ninja_table()
|
||||
*
|
||||
* @param string $content The post content.
|
||||
*
|
||||
* @return string Post content with the Ninja Tables data.
|
||||
*/
|
||||
function relevanssi_index_ninja_tables( $content ) {
|
||||
$m = preg_match_all(
|
||||
'/.*\[ninja_tables.*?id=["\'](\d+)["\'].*?\]/im',
|
||||
$content,
|
||||
$matches,
|
||||
PREG_PATTERN_ORDER
|
||||
);
|
||||
if ( ! $m ) {
|
||||
return $content;
|
||||
}
|
||||
foreach ( $matches[1] as $table_id ) {
|
||||
$content .= ' ' . relevanssi_index_ninja_table( $table_id );
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string containing a Ninja Table table contents.
|
||||
*
|
||||
* The string contains the caption and the values from each row. The table
|
||||
* title and description are also included, if they are set visible on the
|
||||
* frontend.
|
||||
*
|
||||
* @uses $wpdb WordPress database abstraction.
|
||||
*
|
||||
* @param int $table_id The table ID.
|
||||
*
|
||||
* @return string The table content as a string.
|
||||
*/
|
||||
function relevanssi_index_ninja_table( $table_id ) {
|
||||
global $wpdb;
|
||||
$table_post = get_post( $table_id );
|
||||
$table_settings = get_post_meta( $table_id, '_ninja_table_settings', true );
|
||||
$table_contents = '';
|
||||
|
||||
if ( isset( $table_settings['show_description'] ) && '1' === $table_settings['show_description'] ) {
|
||||
$table_contents .= ' ' . $table_post->post_content;
|
||||
}
|
||||
if ( isset( $table_settings['show_title'] ) && '1' === $table_settings['show_title'] ) {
|
||||
$table_contents .= ' ' . $table_post->post_title;
|
||||
}
|
||||
$table_contents .= ' ' . get_post_meta( $table_id, '_ninja_table_caption', true );
|
||||
|
||||
$rows = $wpdb->get_results(
|
||||
$wpdb->prepare(
|
||||
"SELECT value FROM {$wpdb->prefix}ninja_table_items WHERE table_id=%d",
|
||||
$table_id
|
||||
)
|
||||
);
|
||||
foreach ( $rows as $row ) {
|
||||
$array_values = array_map(
|
||||
function ( $value ) {
|
||||
if ( is_object( $value ) ) {
|
||||
return '';
|
||||
}
|
||||
return strval( $value );
|
||||
},
|
||||
array_values( get_object_vars( json_decode( $row->value ) ) )
|
||||
);
|
||||
|
||||
$table_contents .= ' ' . implode( ' ', $array_values );
|
||||
}
|
||||
|
||||
return $table_contents;
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/oxygen.php
|
||||
*
|
||||
* Oxygen Builder compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_custom_field_value', 'relevanssi_oxygen_compatibility', 10, 3 );
|
||||
add_filter( 'relevanssi_index_custom_fields', 'relevanssi_add_oxygen' );
|
||||
add_filter( 'option_relevanssi_index_fields', 'relevanssi_oxygen_fix_none_setting' );
|
||||
add_filter( 'relevanssi_oxygen_section_content', 'relevanssi_oxygen_code_block' );
|
||||
add_filter( 'relevanssi_oxygen_section_content', 'relevanssi_oxygen_rich_text' );
|
||||
add_action( 'save_post', 'relevanssi_insert_edit', 99, 1 );
|
||||
|
||||
/**
|
||||
* Cleans up the Oxygen Builder custom field for Relevanssi consumption.
|
||||
*
|
||||
* Splits up the big custom field content from ct_builder_shortcodes into
|
||||
* sections ([ct_section] tags). Each section can be processed with filters
|
||||
* defined with `relevanssi_oxygen_section_filters`, for example to remove
|
||||
* sections based on their "nicename" or "ct_category" values. After that the
|
||||
* section is passed through the `relevanssi_oxygen_section_content` filter.
|
||||
* Finally all shortcode tags are removed, leaving just the content.
|
||||
*
|
||||
* @param array $value An array of custom field values.
|
||||
* @param string $field The name of the custom field. This function only looks
|
||||
* at `ct_builder_shortcodes` fields.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return array|null An array of custom field values, null if no value exists.
|
||||
*/
|
||||
function relevanssi_oxygen_compatibility( $value, $field, $post_id ) {
|
||||
if ( 'ct_builder_json' === $field ) {
|
||||
$json = array();
|
||||
foreach ( $value as $row ) {
|
||||
$json[] = json_decode( $row );
|
||||
}
|
||||
|
||||
$content = '';
|
||||
if ( isset( $json[0]->children ) ) {
|
||||
foreach ( $json[0]->children as $child ) {
|
||||
$content .= relevanssi_process_oxygen_child( $child );
|
||||
}
|
||||
}
|
||||
|
||||
$value[0] = $content;
|
||||
return $value;
|
||||
}
|
||||
|
||||
if ( 'ct_builder_shortcodes_revisions_dates' === $field ) {
|
||||
return '';
|
||||
}
|
||||
if ( 'ct_builder_shortcodes_revisions' === $field ) {
|
||||
return '';
|
||||
}
|
||||
if ( 'ct_builder_shortcodes' === $field ) {
|
||||
if ( version_compare( CT_VERSION, '4.0', '>=' ) ) {
|
||||
return null;
|
||||
}
|
||||
if ( empty( $value ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$content_tags = explode( '[ct_section', $value[0] );
|
||||
$page_content = '';
|
||||
|
||||
foreach ( $content_tags as $content ) {
|
||||
if ( empty( $content ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( '[' !== substr( $content, 0, 1 ) ) {
|
||||
$content = '[ct_section' . $content;
|
||||
}
|
||||
/**
|
||||
* Allows defining filters to remove Oxygen Builder sections.
|
||||
*
|
||||
* The filters are arrays, with the array key defining the key and
|
||||
* the value defining the value. If the filter array is
|
||||
* array( 'nicename' => 'Hero BG' ), Relevanssi will look for
|
||||
* sections that have "nicename":"Hero BG" in their settings and
|
||||
* will remove those.
|
||||
*
|
||||
* @param array An array of filtering rules, defaults empty.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
$filters = apply_filters(
|
||||
'relevanssi_oxygen_section_filters',
|
||||
array()
|
||||
);
|
||||
array_walk(
|
||||
$filters,
|
||||
function ( $filter ) use ( &$content ) {
|
||||
foreach ( $filter as $key => $value ) {
|
||||
if ( stristr( $content, '"' . $key . '":"' . $value . '"' ) !== false ) {
|
||||
$content = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$content = preg_replace(
|
||||
array(
|
||||
'/\[oxygen.*?\]/',
|
||||
'/\[\/?ct_.*?\]/',
|
||||
'/\[\/?oxy_.*?\]/',
|
||||
),
|
||||
' ',
|
||||
/**
|
||||
* Filters the Oxygen Builder section content before the
|
||||
* Oxygen Builder shortcode tags are removed.
|
||||
*
|
||||
* @param string $content The single section content.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
apply_filters(
|
||||
'relevanssi_oxygen_section_content',
|
||||
$content,
|
||||
$post_id
|
||||
)
|
||||
);
|
||||
|
||||
$page_content .= $content;
|
||||
}
|
||||
|
||||
$page_content = relevanssi_do_shortcode( $page_content );
|
||||
|
||||
$value[0] = $page_content;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively processes the Oxygen JSON data.
|
||||
*
|
||||
* This function extracts all the ct_content data from the JSON. All elements
|
||||
* are run through the relevanssi_oxygen_element filter hook. You can use that
|
||||
* filter hook to modify or to eliminate elements from the JSON.
|
||||
*
|
||||
* @param array $child The child element array.
|
||||
*
|
||||
* @return string The content from the child and the grandchildren.
|
||||
*/
|
||||
function relevanssi_process_oxygen_child( $child ): string {
|
||||
/**
|
||||
* Filters the Oxygen JSON child element.
|
||||
*
|
||||
* If the filter returns an empty value, the child element and all its
|
||||
* children will be ignored.
|
||||
*
|
||||
* @param array $child The JSON child element.
|
||||
*/
|
||||
$child = apply_filters( 'relevanssi_oxygen_element', $child );
|
||||
if ( empty( $child ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$child_content = ' ';
|
||||
if ( isset( $child->options->ct_content ) ) {
|
||||
$child_content .= $child->options->ct_content;
|
||||
}
|
||||
|
||||
if ( isset( $child->options->original->{'code-php'} ) ) {
|
||||
// For code and HTML blocks, strip all tags.
|
||||
$child_content .= wp_strip_all_tags( $child->options->original->{'code-php'} );
|
||||
}
|
||||
|
||||
if ( isset( $child->children ) ) {
|
||||
foreach ( $child->children as $grandchild ) {
|
||||
$child_content .= relevanssi_process_oxygen_child( $grandchild );
|
||||
}
|
||||
}
|
||||
|
||||
return $child_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Oxygen custom field to the list of indexed custom fields.
|
||||
*
|
||||
* @param array|boolean $fields An array of custom fields to index, or false.
|
||||
*
|
||||
* @return array An array of custom fields, including `ct_builder_json` or
|
||||
* `ct_builder_shortcodes`.
|
||||
*/
|
||||
function relevanssi_add_oxygen( $fields ) {
|
||||
$oxygen_field = version_compare( CT_VERSION, '4.0', '>=' )
|
||||
? 'ct_builder_json'
|
||||
: 'ct_builder_shortcodes';
|
||||
if ( ! is_array( $fields ) ) {
|
||||
$fields = array();
|
||||
}
|
||||
if ( ! in_array( $oxygen_field, $fields, true ) ) {
|
||||
$fields[] = $oxygen_field;
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the Oxygen builder shortcode is included in the index, even when
|
||||
* the custom field setting is set to 'none'.
|
||||
*
|
||||
* @param string $value The custom field indexing setting value. The parameter
|
||||
* is ignored, Relevanssi disables this filter and then checks the option to
|
||||
* see what the value is.
|
||||
*
|
||||
* @return string If value is undefined, it's set to 'ct_builder_json' or
|
||||
* 'ct_builder_shortcodes'.
|
||||
*/
|
||||
function relevanssi_oxygen_fix_none_setting( $value ) {
|
||||
if ( ! $value ) {
|
||||
$value = version_compare( CT_VERSION, '4.0', '>=' )
|
||||
? 'ct_builder_json'
|
||||
: 'ct_builder_shortcodes';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes the Base64 encoded PHP & HTML code block contents.
|
||||
*
|
||||
* @param string $content The section content from the
|
||||
* relevanssi_oxygen_section_content filter hook.
|
||||
*
|
||||
* @return string $content The content with the decoded code block content
|
||||
* added to the end.
|
||||
*/
|
||||
function relevanssi_oxygen_code_block( $content ) {
|
||||
if ( preg_match_all( '/\[ct_code_block.*?ct_code_block\]/', $content, $matches ) ) {
|
||||
foreach ( $matches[0] as $match ) {
|
||||
if ( preg_match_all( '/"code-php":"(.*?)"/', $match, $block_matches ) ) {
|
||||
foreach ( $block_matches[1] as $encoded_text ) {
|
||||
$content .= ' ' . base64_decode( $encoded_text ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the Oxygen rich text shortcode.
|
||||
*
|
||||
* @param string $content The content of the Oxygen section.
|
||||
*
|
||||
* @return string The content with the oxy_rich_text shortcodes removed.
|
||||
*/
|
||||
function relevanssi_oxygen_rich_text( $content ) {
|
||||
$content = preg_replace( '/\[\/?oxy_rich_text.*?\]/im', '', $content );
|
||||
return $content;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/paidmembershippro.php
|
||||
*
|
||||
* Paid Membership Pro compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_ok', 'relevanssi_paidmembershippro_compatibility', 10, 2 );
|
||||
|
||||
/**
|
||||
* Checks whether the user is allowed to see the post.
|
||||
*
|
||||
* @param boolean $post_ok Can the post be shown to the user.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return boolean $post_ok True if the user is allowed to see the post,
|
||||
* otherwise false.
|
||||
*/
|
||||
function relevanssi_paidmembershippro_compatibility( $post_ok, $post_id ) {
|
||||
$pmpro_active = get_option( 'pmpro_filterqueries', 0 );
|
||||
|
||||
if ( $pmpro_active ) {
|
||||
$status = relevanssi_get_post_status( $post_id );
|
||||
|
||||
if ( 'publish' === $status ) {
|
||||
// Only apply to published posts, don't apply to drafts.
|
||||
$current_user = wp_get_current_user();
|
||||
$post_ok = pmpro_has_membership_access( $post_id, $current_user->ID );
|
||||
}
|
||||
}
|
||||
|
||||
return $post_ok;
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/polylang.php
|
||||
*
|
||||
* Polylang compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_modify_wp_query', 'relevanssi_polylang_filter' );
|
||||
add_filter( 'relevanssi_where', 'relevanssi_polylang_where_include_terms' );
|
||||
add_filter( 'relevanssi_hits_filter', 'relevanssi_polylang_term_filter' );
|
||||
|
||||
/**
|
||||
* Removes the Polylang language filters.
|
||||
*
|
||||
* If the Polylang allow all option ('relevanssi_polylang_all_languages') is
|
||||
* enabled this removes the Polylang language filter. By default Polylang
|
||||
* filters the languages using a taxonomy query.
|
||||
*
|
||||
* @param object $query WP_Query object we need to clean up.
|
||||
*/
|
||||
function relevanssi_polylang_filter( $query ) {
|
||||
$polylang_allow_all = get_option( 'relevanssi_polylang_all_languages' );
|
||||
if ( 'on' === $polylang_allow_all ) {
|
||||
$ok_queries = array();
|
||||
|
||||
if ( ! isset( $query->tax_query ) ) {
|
||||
// No tax query set, backing off.
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! isset( $query->tax_query->queries ) || ! is_array( $query->tax_query->queries ) ) {
|
||||
// No tax query set, backing off.
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $query->tax_query->queries as $tax_query ) {
|
||||
if ( isset( $tax_query['taxonomy'] ) && 'language' !== $tax_query['taxonomy'] ) {
|
||||
// Not a language tax query.
|
||||
$ok_queries[] = $tax_query;
|
||||
}
|
||||
}
|
||||
$query->tax_query->queries = $ok_queries;
|
||||
|
||||
if ( isset( $query->query_vars['tax_query'] ) ) {
|
||||
// Tax queries can be here as well, so let's sweep this one too.
|
||||
$ok_queries = array();
|
||||
foreach ( $query->query_vars['tax_query'] as $tax_query ) {
|
||||
if ( isset( $tax_query['taxonomy'] ) ) {
|
||||
if ( 'language' !== $tax_query['taxonomy'] ) {
|
||||
$ok_queries[] = $tax_query;
|
||||
}
|
||||
} else {
|
||||
// Relation parameter most likely.
|
||||
$ok_queries[] = $tax_query;
|
||||
}
|
||||
}
|
||||
$query->query_vars['tax_query'] = $ok_queries;
|
||||
}
|
||||
|
||||
if ( isset( $query->query_vars['taxonomy'] ) && 'language' === $query->query_vars['taxonomy'] ) {
|
||||
// Another way to set the taxonomy.
|
||||
unset( $query->query_vars['taxonomy'] );
|
||||
unset( $query->query_vars['term'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows taxonomy terms in language-restricted searches.
|
||||
*
|
||||
* This is a bit of a hack, where the language taxonomy WHERE clause is modified
|
||||
* on the go to allow all posts with the post ID -1 (which means taxonomy terms
|
||||
* and users). This may break suddenly in updates, but I haven't come up with a
|
||||
* better way so far.
|
||||
*
|
||||
* @param string $where The WHERE clause to modify.
|
||||
*
|
||||
* @return string The WHERE clause with additional filtering included.
|
||||
*
|
||||
* @since 2.1.6
|
||||
*/
|
||||
function relevanssi_polylang_where_include_terms( $where ) {
|
||||
global $wpdb;
|
||||
|
||||
$current_language = substr( get_locale(), 0, 2 );
|
||||
if ( function_exists( 'pll_current_language' ) ) {
|
||||
$current_language = pll_current_language();
|
||||
}
|
||||
$languages = get_terms( array( 'taxonomy' => 'language' ) );
|
||||
$language_id = 0;
|
||||
foreach ( $languages as $language ) {
|
||||
if (
|
||||
! is_wp_error( $language ) &&
|
||||
$language instanceof WP_Term &&
|
||||
$language->slug === $current_language
|
||||
) {
|
||||
$language_id = intval( $language->term_id );
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Language ID should now have current language ID.
|
||||
if ( 0 !== $language_id ) {
|
||||
// Do a simple search-and-replace to modify the query.
|
||||
$where = preg_replace( '/\s+/', ' ', $where );
|
||||
$where = preg_replace( '/\(\s/', '(', $where );
|
||||
$where = str_replace(
|
||||
"AND relevanssi.doc IN (SELECT DISTINCT(tr.object_id) FROM {$wpdb->prefix}term_relationships AS tr WHERE tr.term_taxonomy_id IN ($language_id))",
|
||||
"AND (relevanssi.doc IN ( SELECT DISTINCT(tr.object_id) FROM {$wpdb->prefix}term_relationships AS tr WHERE tr.term_taxonomy_id IN ($language_id)) OR (relevanssi.doc = -1))",
|
||||
$where
|
||||
);
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out taxonomy terms in the wrong language.
|
||||
*
|
||||
* If all languages are not allowed, this filter goes through the results and
|
||||
* removes the taxonomy terms in the wrong language. This can't be done in the
|
||||
* original query because the term language information is slightly hard to
|
||||
* find.
|
||||
*
|
||||
* @param array $hits The found posts are in $hits[0].
|
||||
*
|
||||
* @return array The $hits array with the unwanted posts removed.
|
||||
*
|
||||
* @since 2.1.6
|
||||
*/
|
||||
function relevanssi_polylang_term_filter( $hits ) {
|
||||
$polylang_allow_all = get_option( 'relevanssi_polylang_all_languages' );
|
||||
if ( 'on' !== $polylang_allow_all ) {
|
||||
$current_language = substr( get_locale(), 0, 2 );
|
||||
if ( function_exists( 'pll_current_language' ) ) {
|
||||
$current_language = pll_current_language();
|
||||
}
|
||||
$accepted_hits = array();
|
||||
foreach ( $hits[0] as $hit ) {
|
||||
$original_hit = $hit;
|
||||
if ( is_numeric( $hit ) ) {
|
||||
// In case "fields" is set to "ids", fetch the post object we need.
|
||||
$original_hit = $hit;
|
||||
$hit = get_post( $hit );
|
||||
}
|
||||
if ( ! isset( $hit->post_content ) && isset( $hit->ID ) ) {
|
||||
// The "fields" is set to "id=>parent".
|
||||
$original_hit = $hit;
|
||||
$hit = get_post( $hit->ID );
|
||||
}
|
||||
|
||||
if ( isset( $hit->ID ) && -1 === $hit->ID && isset( $hit->term_id ) ) {
|
||||
$term_id = intval( $hit->term_id );
|
||||
$translations = pll_get_term_translations( $term_id );
|
||||
if (
|
||||
isset( $translations[ $current_language ] ) &&
|
||||
$translations[ $current_language ] === $term_id
|
||||
) {
|
||||
$accepted_hits[] = $original_hit;
|
||||
}
|
||||
} else {
|
||||
$accepted_hits[] = $original_hit;
|
||||
}
|
||||
}
|
||||
$hits[0] = $accepted_hits;
|
||||
}
|
||||
return $hits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the term_taxonomy_id matching the Polylang language based on locale.
|
||||
*
|
||||
* @param string $locale The locale string for the language.
|
||||
*
|
||||
* @return int The term_taxonomy_id for the language; 0 if nothing is found.
|
||||
*/
|
||||
function relevanssi_get_language_term_taxonomy_id( $locale ) {
|
||||
global $wpdb, $relevanssi_language_term_ids;
|
||||
|
||||
if ( isset( $relevanssi_language_term_ids[ $locale ] ) ) {
|
||||
return $relevanssi_language_term_ids[ $locale ];
|
||||
}
|
||||
|
||||
$languages = $wpdb->get_results(
|
||||
"SELECT term_taxonomy_id, description FROM $wpdb->term_taxonomy " .
|
||||
"WHERE taxonomy = 'language'"
|
||||
);
|
||||
$term_id = 0;
|
||||
foreach ( $languages as $row ) {
|
||||
$description = unserialize( $row->description ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions
|
||||
if ( $description['locale'] === $locale ) {
|
||||
$term_id = $row->term_taxonomy_id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$relevanssi_language_term_ids[ $locale ] = $term_id;
|
||||
|
||||
return $term_id;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/pretty-links.php
|
||||
*
|
||||
* Pretty Links compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_admin_search_ok', 'relevanssi_pretty_links_ok', 10, 2 );
|
||||
add_filter( 'relevanssi_prevent_default_request', 'relevanssi_pretty_links_ok', 10, 2 );
|
||||
add_filter( 'relevanssi_search_ok', 'relevanssi_pretty_links_ok', 10, 2 );
|
||||
|
||||
/**
|
||||
* Returns false if the query post type is set to 'pretty-link'.
|
||||
*
|
||||
* @param boolean $ok Whether to allow the query.
|
||||
* @param WP_Query $query The WP_Query object.
|
||||
*
|
||||
* @return boolean False if this is a Pretty Links query.
|
||||
*/
|
||||
function relevanssi_pretty_links_ok( $ok, $query ) {
|
||||
if ( isset( $query->query['post_type'] ) && 'pretty-link' === $query->query['post_type'] ) {
|
||||
$ok = false;
|
||||
}
|
||||
return $ok;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/product-gtin-ean-upc-isbn-for-woocommerce.php.php
|
||||
*
|
||||
* Adds Product GTIN (EAN, UPC, ISBN) for WooCommerce support for Relevanssi.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_action( 'pre_option_wpm_pgw_search_by_code', 'relevanssi_disable_gtin_code' );
|
||||
add_filter( 'relevanssi_index_custom_fields', 'relevanssi_add_wpm_gtin_code' );
|
||||
add_filter( 'option_relevanssi_index_fields', 'relevanssi_wpm_pgw_fix_none_setting' );
|
||||
|
||||
/**
|
||||
* Disables the 'wpm_pgw_search_by_code' option.
|
||||
*
|
||||
* If this option is enabled, it will break Relevanssi search when there's a
|
||||
* match for the code.
|
||||
*
|
||||
* @return string 'no'.
|
||||
*/
|
||||
function relevanssi_disable_gtin_code() {
|
||||
return 'no';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the `_wpm_gtin_code` to the list of indexed custom fields.
|
||||
*
|
||||
* @param array|boolean $fields An array of custom fields to index, or false.
|
||||
*
|
||||
* @return array An array of custom fields, including `_wpm_gtin_code`.
|
||||
*/
|
||||
function relevanssi_add_wpm_gtin_code( $fields ) {
|
||||
if ( ! is_array( $fields ) ) {
|
||||
$fields = array();
|
||||
}
|
||||
if ( ! in_array( '_wpm_gtin_code', $fields, true ) ) {
|
||||
$fields[] = '_wpm_gtin_code';
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure the GTIN code is included in the index, even when the custom field
|
||||
* setting is set to 'none'.
|
||||
*
|
||||
* @param string $value The custom field indexing setting value. The parameter
|
||||
* is ignored, Relevanssi disables this filter and then checks the option to
|
||||
* see what the value is.
|
||||
*
|
||||
* @return string If value is undefined, it's set to '_wpm_gtin_code'.
|
||||
*/
|
||||
function relevanssi_wpm_pgw_fix_none_setting( $value ) {
|
||||
if ( ! $value ) {
|
||||
$value = '_wpm_gtin_code';
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/rankmath.php
|
||||
*
|
||||
* Rank Math noindex filtering function.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_do_not_index', 'relevanssi_rankmath_noindex', 10, 2 );
|
||||
add_filter( 'relevanssi_indexing_restriction', 'relevanssi_rankmath_exclude' );
|
||||
add_action( 'relevanssi_indexing_tab_advanced', 'relevanssi_rankmath_form', 20 );
|
||||
add_action( 'relevanssi_indexing_options', 'relevanssi_rankmath_options' );
|
||||
|
||||
/**
|
||||
* Blocks indexing of posts marked "noindex" in the Rank Math settings.
|
||||
*
|
||||
* Attaches to the 'relevanssi_do_not_index' filter hook.
|
||||
*
|
||||
* @param boolean $do_not_index True, if the post shouldn't be indexed.
|
||||
* @param integer $post_id The post ID number.
|
||||
*
|
||||
* @return string|boolean If the post shouldn't be indexed, this returns
|
||||
* 'RankMath'. The value may also be a boolean.
|
||||
*/
|
||||
function relevanssi_rankmath_noindex( $do_not_index, $post_id ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $do_not_index;
|
||||
}
|
||||
$noindex = get_post_meta( $post_id, 'rank_math_robots', true );
|
||||
if ( is_array( $noindex ) && in_array( 'noindex', $noindex, true ) ) {
|
||||
$do_not_index = 'RankMath';
|
||||
}
|
||||
return $do_not_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes the "noindex" posts from Relevanssi indexing.
|
||||
*
|
||||
* Adds a MySQL query restriction that blocks posts that have the Rank Math
|
||||
* "rank_math_robots" setting set to something that includes "noindex".
|
||||
*
|
||||
* @param array $restriction An array with two values: 'mysql' for the MySQL
|
||||
* query restriction to modify, 'reason' for the reason of restriction.
|
||||
*/
|
||||
function relevanssi_rankmath_exclude( $restriction ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
// Backwards compatibility code for 2.8.0, remove at some point.
|
||||
if ( is_string( $restriction ) ) {
|
||||
$restriction = array(
|
||||
'mysql' => $restriction,
|
||||
'reason' => '',
|
||||
);
|
||||
}
|
||||
|
||||
$restriction['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM
|
||||
$wpdb->postmeta WHERE meta_key = 'rank_math_robots'
|
||||
AND meta_value LIKE '%noindex%' ) ";
|
||||
$restriction['reason'] .= ' Rank Math';
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the form fields for disabling the feature.
|
||||
*/
|
||||
function relevanssi_rankmath_form() {
|
||||
$seo_noindex = get_option( 'relevanssi_seo_noindex' );
|
||||
$seo_noindex = relevanssi_check( $seo_noindex );
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for='relevanssi_seo_noindex'><?php esc_html_e( 'Use Rank Math SEO noindex', 'relevanssi' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<label for='relevanssi_seo_noindex'>
|
||||
<input type='checkbox' name='relevanssi_seo_noindex' id='relevanssi_seo_noindex' <?php echo esc_attr( $seo_noindex ); ?> />
|
||||
<?php esc_html_e( 'Use Rank Math SEO noindex.', 'relevanssi' ); ?>
|
||||
</label>
|
||||
<p class="description"><?php esc_html_e( 'If checked, Relevanssi will not index posts marked as "No index" in Rank Math SEO settings.', 'relevanssi' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the SEO No index option.
|
||||
*
|
||||
* @param array $request An array of option values from the request.
|
||||
*/
|
||||
function relevanssi_rankmath_options( array $request ) {
|
||||
relevanssi_update_off_or_on( $request, 'relevanssi_seo_noindex', true );
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/restrictcontentpro.php
|
||||
*
|
||||
* Restrict Content Pro compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_ok', 'relevanssi_restrictcontentpro_compatibility', 10, 2 );
|
||||
|
||||
/**
|
||||
* Checks whether the user is allowed to see the post.
|
||||
*
|
||||
* @param boolean $post_ok Can the post be shown to the user.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return boolean $post_ok True if the user is allowed to see the post,
|
||||
* otherwise false.
|
||||
*/
|
||||
function relevanssi_restrictcontentpro_compatibility( $post_ok, $post_id ) {
|
||||
if ( ! $post_ok ) {
|
||||
return $post_ok;
|
||||
}
|
||||
|
||||
$post_ok = rcp_user_can_access( get_current_user_id(), $post_id );
|
||||
|
||||
return $post_ok;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/seoframework.php
|
||||
*
|
||||
* The SEO Framework noindex filtering function.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_do_not_index', 'relevanssi_seoframework_noindex', 10, 2 );
|
||||
add_filter( 'relevanssi_indexing_restriction', 'relevanssi_seoframework_exclude' );
|
||||
add_action( 'relevanssi_indexing_tab_advanced', 'relevanssi_seoframework_form', 20 );
|
||||
add_action( 'relevanssi_indexing_options', 'relevanssi_seoframework_options' );
|
||||
|
||||
/**
|
||||
* Blocks indexing of posts marked "Exclude this page from all search queries
|
||||
* on this site." in the SEO Framework settings.
|
||||
*
|
||||
* Attaches to the 'relevanssi_do_not_index' filter hook.
|
||||
*
|
||||
* @param boolean $do_not_index True, if the post shouldn't be indexed.
|
||||
* @param integer $post_id The post ID number.
|
||||
*
|
||||
* @return string|boolean If the post shouldn't be indexed, this returns
|
||||
* 'SEO Framework'. The value may also be a boolean.
|
||||
*/
|
||||
function relevanssi_seoframework_noindex( $do_not_index, $post_id ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $do_not_index;
|
||||
}
|
||||
|
||||
$noindex = get_post_meta( $post_id, 'exclude_local_search', true );
|
||||
if ( '1' === $noindex ) {
|
||||
$do_not_index = 'SEO Framework';
|
||||
}
|
||||
return $do_not_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes the "noindex" posts from Relevanssi indexing.
|
||||
*
|
||||
* Adds a MySQL query restriction that blocks posts that have the SEO Framework
|
||||
* "Exclude this page from all search queries on this site" setting set to "1"
|
||||
* from indexing.
|
||||
*
|
||||
* @param array $restriction An array with two values: 'mysql' for the MySQL
|
||||
* query restriction to modify, 'reason' for the reason of restriction.
|
||||
*/
|
||||
function relevanssi_seoframework_exclude( $restriction ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$restriction['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM
|
||||
$wpdb->postmeta WHERE meta_key = 'exclude_local_search'
|
||||
AND meta_value = '1' ) ";
|
||||
$restriction['reason'] .= ' SEO Framework';
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the form fields for disabling the feature.
|
||||
*/
|
||||
function relevanssi_seoframework_form() {
|
||||
$seo_noindex = get_option( 'relevanssi_seo_noindex' );
|
||||
$seo_noindex = relevanssi_check( $seo_noindex );
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for='relevanssi_seo_noindex'><?php esc_html_e( 'Use SEO Framework noindex', 'relevanssi' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<label for='relevanssi_seo_noindex'>
|
||||
<input type='checkbox' name='relevanssi_seo_noindex' id='relevanssi_seo_noindex' <?php echo esc_attr( $seo_noindex ); ?> />
|
||||
<?php esc_html_e( 'Use SEO Framework noindex.', 'relevanssi' ); ?>
|
||||
</label>
|
||||
<p class="description"><?php esc_html_e( 'If checked, Relevanssi will not index posts marked as "No index" in SEO Framework settings.', 'relevanssi' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the SEO No index option.
|
||||
*
|
||||
* @param array $request An array of option values from the request.
|
||||
*/
|
||||
function relevanssi_seoframework_options( array $request ) {
|
||||
relevanssi_update_off_or_on( $request, 'relevanssi_seo_noindex', true );
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/seopress.php
|
||||
*
|
||||
* SEOPress noindex filtering function.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Benjamin Denis
|
||||
* @source ./yoast-seo.php (Mikko Saari)
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_do_not_index', 'relevanssi_seopress_noindex', 10, 2 );
|
||||
add_filter( 'relevanssi_indexing_restriction', 'relevanssi_seopress_exclude' );
|
||||
add_action( 'relevanssi_indexing_tab_advanced', 'relevanssi_seopress_form', 20 );
|
||||
add_action( 'relevanssi_indexing_options', 'relevanssi_seopress_options' );
|
||||
|
||||
/**
|
||||
* Blocks indexing of posts marked "noindex" in the SEOPress settings.
|
||||
*
|
||||
* Attaches to the 'relevanssi_do_not_index' filter hook.
|
||||
*
|
||||
* @param boolean $do_not_index True, if the post shouldn't be indexed.
|
||||
* @param integer $post_id The post ID number.
|
||||
*
|
||||
* @return string|boolean If the post shouldn't be indexed, this returns
|
||||
* 'seopress'. The value may also be a boolean.
|
||||
*/
|
||||
function relevanssi_seopress_noindex( $do_not_index, $post_id ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $do_not_index;
|
||||
}
|
||||
|
||||
$noindex = get_post_meta( $post_id, '_seopress_robots_index', true );
|
||||
if ( 'yes' === $noindex ) {
|
||||
$do_not_index = 'SEOPress';
|
||||
}
|
||||
return $do_not_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Excludes the "noindex" posts from Relevanssi indexing.
|
||||
*
|
||||
* Adds a MySQL query restriction that blocks posts that have the SEOPress
|
||||
* "noindex" setting set to "1" from indexing.
|
||||
*
|
||||
* @param array $restriction An array with two values: 'mysql' for the MySQL
|
||||
* query restriction to modify, 'reason' for the reason of restriction.
|
||||
*/
|
||||
function relevanssi_seopress_exclude( $restriction ) {
|
||||
if ( 'on' !== get_option( 'relevanssi_seo_noindex' ) ) {
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
// Backwards compatibility code for 2.8.0, remove at some point.
|
||||
if ( is_string( $restriction ) ) {
|
||||
$restriction = array(
|
||||
'mysql' => $restriction,
|
||||
'reason' => '',
|
||||
);
|
||||
}
|
||||
|
||||
$restriction['mysql'] .= " AND post.ID NOT IN (SELECT post_id FROM
|
||||
$wpdb->postmeta WHERE meta_key = '_seopress_robots_index'
|
||||
AND meta_value = 'yes' ) ";
|
||||
$restriction['reason'] .= 'SEOPress';
|
||||
return $restriction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the form fields for disabling the feature.
|
||||
*/
|
||||
function relevanssi_seopress_form() {
|
||||
$seo_noindex = get_option( 'relevanssi_seo_noindex' );
|
||||
$seo_noindex = relevanssi_check( $seo_noindex );
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for='relevanssi_seo_noindex'><?php esc_html_e( 'Use SEOPress noindex', 'relevanssi' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<label for='relevanssi_seo_noindex'>
|
||||
<input type='checkbox' name='relevanssi_seo_noindex' id='relevanssi_seo_noindex' <?php echo esc_attr( $seo_noindex ); ?> />
|
||||
<?php esc_html_e( 'Use SEOPress noindex.', 'relevanssi' ); ?>
|
||||
</label>
|
||||
<p class="description"><?php esc_html_e( 'If checked, Relevanssi will not index posts marked as "No index" in SEOPress settings.', 'relevanssi' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the SEO No index option.
|
||||
*
|
||||
* @param array $request An array of option values from the request.
|
||||
*/
|
||||
function relevanssi_seopress_options( array $request ) {
|
||||
relevanssi_update_off_or_on( $request, 'relevanssi_seo_noindex', true );
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* /lib/compatibility/simplemembership.php
|
||||
*
|
||||
* Simple Membership compatibility features.
|
||||
*
|
||||
* @package Relevanssi
|
||||
* @author Mikko Saari
|
||||
* @license https://wordpress.org/about/gpl/ GNU General Public License
|
||||
* @see https://www.relevanssi.com/
|
||||
*/
|
||||
|
||||
add_filter( 'relevanssi_post_ok', 'relevanssi_simplemembership_compatibility', 10, 2 );
|
||||
|
||||
/**
|
||||
* Checks whether the user is allowed to see the post.
|
||||
*
|
||||
* @param boolean $post_ok Can the post be shown to the user.
|
||||
* @param int $post_id The post ID.
|
||||
*
|
||||
* @return boolean $post_ok True if the user is allowed to see the post,
|
||||
* otherwise false.
|
||||
*/
|
||||
function relevanssi_simplemembership_compatibility( $post_ok, $post_id ) {
|
||||
$access_ctrl = SwpmAccessControl::get_instance();
|
||||
$post = get_post( $post_id );
|
||||
$post_ok = $access_ctrl->can_i_read_post( $post );
|
||||
|
||||
return $post_ok;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user