Файловый менеджер - Редактировать - /home/avadvi5/public_html/fcolliver.com/wp-content/plugins/wpforms/src/Pro/Admin/PluginList.php
Ðазад
<?php namespace WPForms\Pro\Admin; // phpcs:disable WPForms.PHP.UseStatement.UnusedUseStatement use WP_Plugins_List_Table; use stdClass; use WPForms\Admin\Addons\AddonsCache; // phpcs:enable WPForms.PHP.UseStatement.UnusedUseStatement /** * Class PluginList. * * Notice displayed in the Plugins page for Pro users. * * @since 1.8.6 */ class PluginList { /** * License Statuses. * * @since 1.8.6 * @since 1.9.5 Added new `limit_reached` and `flagged` statuses. */ const LICENSE_STATUS_EMPTY = 'empty'; const LICENSE_STATUS_VALID = 'valid'; const LICENSE_STATUS_EXPIRED = 'expired'; const LICENSE_STATUS_DISABLED = 'disabled'; const LICENSE_STATUS_INVALID = 'invalid'; const LICENSE_STATUS_LIMIT_REACHED = 'limit_reached'; const LICENSE_STATUS_FLAGGED = 'flagged'; /** * Plugin slug. * * @since 1.8.6 * * @var string */ private $plugin_slug; /** * Plugin path (relative to the plugins' dir). * * @since 1.8.6 * * @var string */ private $plugin_path; /** * The license status. * * @since 1.8.6 * * @var string|null */ private $license_status; /** * The latest version fetched from a remote source. * * @since 1.8.6 * * @var null|string */ private $remote_latest_version; /** * Whether this site is using the latest version of WPForms Pro. * * @since 1.8.6 * * @var bool */ private $is_using_latest_version; /** * Internal set_site_transient_update_addons cache. * * @since 1.9.0 * * @var object|null */ private $update_addons_cache; /** * Instance of AddonsCache. * * @since 1.9.0 * * @var AddonsCache|null */ private $addons_cache_obj; /** * Init. * * @since 1.8.6 * * @return void */ public function init() { $this->plugin_slug = defined( 'WPFORMS_PLUGIN_DIR' ) ? plugin_basename( WPFORMS_PLUGIN_DIR ) : 'wpforms'; $this->plugin_path = $this->plugin_slug . '/wpforms.php'; $this->addons_cache_obj = wpforms()->obj( 'addons_cache' ); ( new PluginListDisabler() )->init( $this->is_valid_license() ); $this->hooks(); } /** * Register hooks. * * @since 1.8.6 * * @return void */ private function hooks() { global $pagenow; if ( empty( $pagenow ) || $pagenow !== 'plugins.php' ) { return; } add_action( 'admin_init', [ $this, 'update_addons_cache' ] ); add_filter( 'site_transient_update_plugins', [ $this, 'site_transient_update_addons' ] ); add_filter( 'set_site_transient_update_plugins', [ $this, 'set_site_transient_update_addons' ] ); add_action( 'admin_head', [ $this, 'add_style' ] ); add_action( "after_plugin_row_{$this->plugin_path}", [ $this, 'show_plugin_notice' ], 0 ); } /** * Update addons cache. * * @since 1.9.0 * * @return void */ public function update_addons_cache() { if ( $this->addons_cache_obj ) { $this->addons_cache_obj->update(); } } /** * Add CSS styles. * * @since 1.8.6 * * @return void */ public function add_style() { printf( '<style> #wpforms-update td.plugin-update { box-shadow: 0 1px 0 0 rgba(0,0,0,.1); transform: translateY(-1px); } .plugins tr.update[data-slug="%1$s"] .second, .plugins tr.update[data-slug="%1$s"] .row-actions { padding-bottom: 0; } .wpforms-wrong-license { color: #dc3232; font-weight: bold; } @media screen and (max-width: 782px) { .plugins tr[data-slug="%1$s"].plugin-update-tr.active:before { background-color: #f0f6fc; border-left: 4px solid #72aee6; } .plugins .plugin-update-tr .wpforms-update-message { margin-left: 0; } } </style>', esc_attr( $this->plugin_slug ) ); } /** * Filters `update_plugins` transient in Admin Plugins page. * * This method removes the "update" of the Pro plugin. * Doing this fixes the edge case where both the default WP plugin update notice * and our custom notice is displayed at the same time. * * @since 1.8.6 * @deprecated 1.9.0 * * @param mixed $value Value of site transient. * * @return object $value Amended WordPress update object. */ public function site_transient_update_plugins( $value ) { // We don't need current method anymore. _deprecated_function( __METHOD__, '1.9.0 of the WPForms plugin' ); return $value; } /** * Filters `update_plugins` transient in Admin Plugins page. * * This method checks available addon updates. * * @since 1.9.0 * * @param mixed $value Value of site transient. * * @return object $value Amended WordPress update object. */ public function site_transient_update_addons( $value ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks, Generic.Metrics.CyclomaticComplexity.TooHigh global $current_screen; // We only want this filter in the Dashboard -> Plugins page. if ( is_null( $current_screen ) || $current_screen->id !== 'plugins' ) { return $value; } if ( $this->update_addons_cache !== null ) { return $this->update_addons_cache; } if ( ! is_object( $value ) ) { $value = new stdClass(); } $addons = $this->addons_cache_obj ? $this->addons_cache_obj->get() : []; /** * Filter the addons list cache. * * @since 1.9.2 * * @param array $addons Addons list cache. */ $addons = apply_filters( 'wpforms_pro_admin_list_addons_cache', $addons ); foreach ( get_plugins() as $name => $plugin ) { $slug = explode( '/', $name )[0]; if ( ! array_key_exists( $slug, $addons ) ) { continue; } $addon = $addons[ $slug ]; if ( version_compare( $plugin['Version'], $addon['version'], '<' ) ) { // Do not set 'slug' here, only 'url', to form $details_url in after_plugin_row() properly. $url = add_query_arg( [ 'utm_source' => 'WordPress', 'utm_campaign' => 'plugin', 'utm_medium' => 'addons', 'utm_content' => $addon['title'], ], $addon['url'] ); $icon_url = WPFORMS_PLUGIN_URL . 'assets/images/' . ( $addon['icon'] ?? 'sullie.png' ); $icons = [ '1x' => $icon_url, '2x' => $icon_url, 'default' => $icon_url, ]; $value->response[ $name ] = (object) [ 'id' => $addon['id'], 'plugin' => $name, 'version' => $plugin['Version'], 'new_version' => $addon['version'] ?? $plugin['Version'], 'url' => $url, 'package' => $value->response[ $name ]->package ?? '', 'icons' => $icons, 'banners' => [], 'banners_rtl' => [], 'requires' => $addon['required_versions']['wp'] ?? '5.5', 'requires_php' => $addon['required_versions']['php'] ?? '7.2', 'requires_wpforms' => $addon['required_versions']['wpforms'] ?? WPFORMS_VERSION, 'requires_plugin' => 'wpforms/wpforms.php', ]; } add_action( "after_plugin_row_{$name}", [ $this, 'after_plugin_row' ], 0, 2 ); } $this->update_addons_cache = $value; return $value; } /** * Set site transient update plugins action. * * Method site_transient_update_addons() is called multiple times, * so we cache it's result internally in this class. * * On set_transient_update_plugins action, we flush internal caches. * * @since 1.9.0 * * @return void */ public function set_site_transient_update_addons() { $this->update_addons_cache = null; } /** * Displays update information for a plugin. * Form of the wp_plugin_update_row(). * * @since 1.9.0 * * @param string $file Plugin basename. * @param array $plugin_data Plugin information. * * @return void|false * @noinspection HtmlUnknownAttribute */ public function after_plugin_row( string $file, array $plugin_data ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks, Generic.Metrics.CyclomaticComplexity.TooHigh // Remove WP Core action, as we override its functionality for the plugin. remove_action( "after_plugin_row_{$file}", 'wp_plugin_update_row' ); $current = get_site_transient( 'update_plugins' ); if ( ! isset( $current->response[ $file ] ) ) { return false; } $response = $current->response[ $file ]; $plugins_allowed_tags = [ 'a' => [ 'href' => [], 'title' => [], ], 'abbr' => [ 'title' => [] ], 'acronym' => [ 'title' => [] ], 'code' => [], 'em' => [], 'strong' => [], ]; $plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowed_tags ); $plugin_chunks = explode( '/', $file ); $plugin_slug = $plugin_chunks[0] ?? $response->id; // We need to remove wordpress.com filter to get proper self_admin_url here. $wp_com_priority = has_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination' ); if ( $wp_com_priority ) { remove_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination' ); } $details_url = add_query_arg( [ 'tab' => 'plugin-information', 'plugin' => $plugin_slug, 'section' => 'changelog', 'TB_iframe' => 'true', 'width' => 772, 'height' => 771, ], self_admin_url( 'plugin-install.php' ) ); // Restore wordpress.com filter. if ( $wp_com_priority ) { add_filter( 'self_admin_url', 'wpcomsh_update_plugin_link_destination', $wp_com_priority, 2 ); } /** * WP List Table. * * @var WP_Plugins_List_Table $wp_list_table */ $wp_list_table = _get_list_table( 'WP_Plugins_List_Table', [ 'screen' => get_current_screen(), ] ); if ( ! is_network_admin() && is_multisite() ) { return; } if ( is_network_admin() ) { $active_class = is_plugin_active_for_network( $file ) ? ' active' : ''; } else { $active_class = is_plugin_active( $file ) ? ' active' : ''; } $requires_php = $response->requires_php ?? ''; $requires_wp = $response->requires ?? ''; $requires_wpforms = $response->requires_wpforms ?? ''; $compatible['php'] = is_php_version_compatible( $requires_php ) ? true : 'PHP ' . $requires_php; $compatible['wp'] = is_wp_version_compatible( $requires_wp ) ? true : 'WordPress ' . $requires_wp; $compatible['wpforms'] = self::is_wpforms_version_compatible( $requires_wpforms ) ? true : 'WPForms ' . $requires_wpforms; $notice_type = 'notice-warning'; foreach ( $compatible as $value ) { if ( $value !== true ) { $notice_type = 'notice-error'; break; } } printf( '<tr class="plugin-update-tr%s" id="%s" data-slug="%s" data-plugin="%s"> <td colspan="%s" class="plugin-update colspanchange"> <div class="wpforms-update-message update-message notice inline %s notice-alt"><p>', esc_attr( $active_class ), esc_attr( $plugin_slug . '-update' ), esc_attr( $plugin_slug ), esc_attr( $file ), esc_attr( $wp_list_table->get_column_count() ), esc_attr( $notice_type ) ); $this->print_addon_update_message( $plugin_name, $details_url, $response, $compatible, $file ); /** * Fires at the end of the update message container in each * row of the plugins' list table. * * The dynamic portion of the hook name, `$file`, refers to the path * of the plugin's primary file relative to the plugins' directory. * * @since 2.8.0 * * @param array $plugin_data An array of plugin metadata. See get_plugin_data() * and the {@see 'plugin_row_meta'} filter for the list * of possible values. * @param object $response { * An object of metadata about the available plugin update. * * @type string $id Plugin ID, e.g. `w.org/plugins/[plugin-name]`. * @type string $slug Plugin slug. * @type string $plugin Plugin basename. * @type string $new_version New plugin version. * @type string $url Plugin URL. * @type string $package Plugin update package URL. * @type string[] $icons An array of plugin icon URLs. * @type string[] $banners An array of plugin banner URLs. * @type string[] $banners_rtl An array of plugin RTL banner URLs. * @type string $requires The version of WordPress which the plugin requires. * @type string $tested The version of WordPress the plugin is tested against. * @type string $requires_php The version of PHP which the plugin requires. * @type string $requires_wp The version of WP which the plugin requires. * @type string $requires_wpforms The version of WPForms which the plugin requires. * } */ do_action( "in_plugin_update_message-{$file}", $plugin_data, $response ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName, WordPress.NamingConventions.ValidHookName.UseUnderscores echo '</p></div></td></tr>'; } /** * Get the license status. * * @since 1.8.6 * * @return string */ private function get_license_status(): string { if ( ! is_null( $this->license_status ) ) { return $this->license_status; } $license_type = wpforms_get_license_type(); $license_key = wpforms_get_license_key(); $this->license_status = self::LICENSE_STATUS_VALID; if ( empty( $license_key ) || empty( $license_type ) ) { $this->license_status = self::LICENSE_STATUS_EMPTY; return $this->license_status; } $this->license_status = wpforms_setting( 'is_expired', false, 'wpforms_license' ) ? self::LICENSE_STATUS_EXPIRED : $this->license_status; $this->license_status = wpforms_setting( 'is_disabled', false, 'wpforms_license' ) ? self::LICENSE_STATUS_DISABLED : $this->license_status; $this->license_status = wpforms_setting( 'is_invalid', false, 'wpforms_license' ) ? self::LICENSE_STATUS_INVALID : $this->license_status; $this->license_status = wpforms_setting( 'is_limit_reached', false, 'wpforms_license' ) ? self::LICENSE_STATUS_LIMIT_REACHED : $this->license_status; $this->license_status = wpforms_setting( 'is_flagged', false, 'wpforms_license' ) ? self::LICENSE_STATUS_FLAGGED : $this->license_status; return $this->license_status; } /** * Check if the license is valid. * * @since 1.9.0 * * @return bool */ public function is_valid_license(): bool { return $this->get_license_status() === self::LICENSE_STATUS_VALID; } /** * Adds custom plugin notice for Pro users without a valid license. * * @since 1.8.6 * * @param string $plugin_file Path to the plugin file relative to the `plugins` directory. * * @return void */ public function show_plugin_notice( string $plugin_file ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks if ( $plugin_file !== $this->plugin_path ) { return; } // Remove WP Core action, as we override its functionality for the plugin. remove_action( "after_plugin_row_{$plugin_file}", 'wp_plugin_update_row' ); $update_notice = $this->get_update_notice(); if ( empty( $update_notice ) ) { return; } global $wp_list_table; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo wpforms_render( 'admin/plugins-list/update-notice', [ 'plugin_slug' => $this->plugin_slug, 'plugin_path' => $this->plugin_path, 'columns_count' => empty( $wp_list_table ) ? 4 : $wp_list_table->get_column_count(), 'update_notice' => $update_notice, ], true ); } /** * Get the update notice. * * @since 1.8.6 * * @return string */ private function get_update_notice(): string { $status = $this->get_license_status(); if ( $status === self::LICENSE_STATUS_VALID ) { return $this->is_using_latest_version() ? '' : $this->get_new_version_available_notice(); } return $status === self::LICENSE_STATUS_EMPTY ? $this->get_no_license_notice() : $this->get_wrong_license_notice( $status ); } /** * Get the notice for users without a license key. * * @since 1.8.6 * * @return string * @noinspection HtmlUnknownTarget */ private function get_no_license_notice(): string { $activate_url = add_query_arg( [ 'page' => 'wpforms-settings' ], admin_url( 'admin.php' ) ); $purchase_url = wpforms_utm_link( 'https://wpforms.com/pricing/', 'no license', 'purchase one now' ); if ( $this->is_using_latest_version() ) { return sprintf( /* translators: %1$s - WPForms Pro URL; %2$s - WPForms Pro purchase link. */ __( '<a href="%1$s">Activate WPForms Pro</a> to receive features, updates, and support. Don\'t have a license? <a target="_blank" href="%2$s" rel="noopener noreferrer">Purchase one now</a>.', 'wpforms' ), esc_url( $activate_url ), esc_url( $purchase_url ) ); } return $this->get_new_version_available_notice() . '<br />' . sprintf( /* translators: %1$s - WPForms Pro URL; %2$s - WPForms Pro purchase link. */ __( '<a href="%1$s">Activate</a> your license to access this update, new features, and support. Don\'t have a license? <a target="_blank" href="%2$s" rel="noopener noreferrer">Purchase one now</a>.', 'wpforms' ), esc_url( $activate_url ), esc_url( $purchase_url ) ); } /** * Get the notice for users with expired license key. * * @since 1.8.6 * * @param string $status License status. * * @return string * @noinspection HtmlUnknownTarget */ private function get_wrong_license_notice( string $status ): string { $message = $this->is_using_latest_version() ? '' : $this->get_new_version_available_notice() . '<br>'; $status_messages = [ self::LICENSE_STATUS_EXPIRED => esc_html__( 'Your WPForms Pro license is expired.', 'wpforms' ), self::LICENSE_STATUS_DISABLED => esc_html__( 'Your WPForms Pro license is disabled.', 'wpforms' ), self::LICENSE_STATUS_INVALID => esc_html__( 'Your WPForms Pro license is invalid.', 'wpforms' ), self::LICENSE_STATUS_LIMIT_REACHED => esc_html__( 'Your WPForms Pro license has no activations left.', 'wpforms' ), self::LICENSE_STATUS_FLAGGED => esc_html__( 'Your WPForms Pro license needs support.', 'wpforms' ), ]; $status_message = $status_messages[ $status ] ?? ''; if ( $status === self::LICENSE_STATUS_FLAGGED ) { $flagged_msg = sprintf( /* translators: %s - WPForms Pro key support link. */ __( 'Before you can activate this key, we\'d like to check in with you. Please <a href="%1$s" target="_blank" rel="noopener noreferrer">reach out to support here.</a>', 'wpforms' ), esc_url( wpforms_utm_link( 'https://wpforms.com/account/key-support/', 'all-plugins', 'Verify Key - Reach out to Support' ) ) ); return "$message<span class='wpforms-wrong-license'>$status_message</span> $flagged_msg"; } $renew_msg = sprintf( /* translators: %s - WPForms Pro renew link. */ __( '<a target="_blank" href="%1$s" rel="noopener noreferrer">Renew now</a> to receive new features, updates, and support.', 'wpforms' ), esc_url( wpforms_utm_link( 'https://wpforms.com/account/licenses/', 'plugins list expired license', 'WPForms' ) ) ); return "$message<span class='wpforms-wrong-license'>$status_message</span> $renew_msg"; } /** * Get the notice to show when a new version of WPForms Pro is available. * * @since 1.8.6 * * @return string * @noinspection HtmlUnknownTarget */ private function get_new_version_available_notice(): string { $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=wpforms§ion=changelog&TB_iframe=true&width=772&height=771' ); $upgrade_url = wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' . $this->plugin_path ), 'upgrade-plugin_' . $this->plugin_path ); $new_version = $this->get_latest_version(); // Message without "update now" link. $new_version_message = sprintf( /* translators: %1$s - WPForms Pro Changelog link; %2$s - WPForms Pro latest version. */ __( 'There is a new version of WPForms available. <a class="thickbox open-plugin-details-modal" href="%1$s" rel="noopener noreferrer">View version %2$s details</a>', 'wpforms' ), esc_url( $details_url ), esc_html( $new_version ) ); if ( $this->get_license_status() !== self::LICENSE_STATUS_VALID ) { return $new_version_message . '.'; } // Message with "update now" link. return $new_version_message . ' ' . sprintf( /* translators: %1$s - WPForms Pro upgrade URL; %2$s - Update now link aria-label attribute. */ __( 'or <a href="%1$s" class="update-link" aria-label="%2$s">update now</a>.', 'wpforms' ), esc_url( $upgrade_url ), esc_attr__( 'Update Now', 'wpforms' ) ); } /** * Whether this site is using the latest version of WPForms Pro. * * @since 1.8.6 * * @return bool */ private function is_using_latest_version(): bool { if ( ! is_null( $this->is_using_latest_version ) ) { return $this->is_using_latest_version; } $this->is_using_latest_version = version_compare( WPFORMS_VERSION, $this->get_latest_version(), '>=' ); return $this->is_using_latest_version; } /** * Get the latest version. * * @since 1.8.6 * * @return string */ private function get_latest_version() { if ( ! is_null( $this->remote_latest_version ) ) { return $this->remote_latest_version; } // WP core updates this transient. // We use it to get the latest version of WPForms Pro. // We have a hook on `pre_set_site_transient_update_plugins` in the `WPForms_Updater` class // that checks the remote API and adds the update for WPForms Pro to this transient. $transient = get_site_transient( 'update_plugins' ); $this->remote_latest_version = $transient->response[ $this->plugin_path ]->new_version ?? WPFORMS_VERSION; return $this->remote_latest_version; } /** * Print addon update message. * * @since 1.9.0 * * @param string $plugin_name Plugin name. * @param string $details_url Details URL. * @param object $response Response. * @param array $compatible Compatibility array. * @param string $file Filename. * * @return void * @noinspection HtmlUnknownTarget * @noinspection HtmlUnknownAttribute */ public function print_addon_update_message( string $plugin_name, string $details_url, $response, array $compatible, string $file ) { $link_attr = sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', esc_attr( sprintf( /* translators: 1: Plugin name, 2: Version number. */ __( 'View %1$s version %2$s details', 'wpforms' ), $plugin_name, $response->new_version ) ) ); // Prepare incompatible components. $incompatible = []; foreach ( $compatible as $key => $value ) { if ( $value !== true ) { $incompatible[ $key ] = $value; } } // Compatible updates. if ( empty( $incompatible ) ) { $this->print_addon_compatible_update_message( $plugin_name, $details_url, $response, $link_attr, $file ); return; } // Incompatible updates available. // Details URL with disabled update button. $details_url = add_query_arg( [ 'update' => 'disabled', 'TB_iframe' => 'true', 'width' => 772, 'height' => 771, ], // Remove query args that is added after `update=disabled`. // This is necessary because WP removes everything from URL after `TB_iframe=true&width=772&height=771`. remove_query_arg( [ 'TB_iframe', 'width', 'height' ], $details_url ) ); $available = wp_kses( sprintf( /* translators: 1: Plugin name, 2: Details URL, 3: Link attributes, 4: Version number, 5: Components. */ __( 'Sorry, the %1$s addon can\'t be updated to <a href="%2$s" %3$s>version %4$s</a> because it requires %5$s.', 'wpforms' ), esc_html( $plugin_name ), esc_url( $details_url ), $link_attr, esc_html( $response->new_version ), wpforms_list_array( $incompatible ) ), [ 'a' => [ 'href' => [], 'class' => [], 'aria-label' => [], ], ] ); $check_updates = wp_kses( sprintf( /* translators: 1: Details URL, 2: Additional link attributes, 3: Version number. */ __( 'If no update is available, try <a href="%1$s">checking for new plugin updates</a>.', 'wpforms' ), esc_url( admin_url( 'update-core.php' ) ) ), [ 'a' => [ 'href' => [], ], ] ); $php_update = ''; if ( ! empty( $incompatible['php'] ) ) { $php_update = sprintf( wp_kses( /* translators: 1:URL to Update PHP page. */ __( 'Learn more about <a href="%1$s" target="_blank" rel="noopener noreferrer">updating PHP</a>.', 'wpforms' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), esc_url( wp_get_update_php_url() ) ); } // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $available . ' ' . $check_updates . ' ' . $php_update; wp_update_php_annotation( '<br><em>', '</em>' ); } /** * Print addon compatible update message. * * @since 1.9.0 * * @param string $plugin_name Plugin name. * @param string $details_url Details URL. * @param object $response Response. * @param string $link_attr Additional link attributes. * @param string $file Filename. * * @return void * @noinspection HtmlUnknownTarget * @noinspection HtmlUnknownAttribute */ public function print_addon_compatible_update_message( string $plugin_name, string $details_url, $response, string $link_attr, string $file ) { $update_now = ''; if ( $this->is_valid_license() && current_user_can( 'update_plugins' ) ) { $update_now = sprintf( ' or <a href="%1$s" %2$s>update now</a>', esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $file, 'upgrade-plugin_' . $file ) ), sprintf( 'class="update-link" aria-label="%s"', /* translators: %s: Plugin name. */ esc_attr( sprintf( __( 'Update %s now', 'wpforms' ), $plugin_name ) ) ) ); } echo wp_kses( sprintf( /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number, 5: Update URL, 6: Additional link attributes. */ __( 'There is a new version of %1$s available. <a href="%2$s" %3$s>View version %4$s details</a>%5$s.', 'wpforms' ), $plugin_name, esc_url( $details_url ), $link_attr, esc_attr( $response->new_version ), $update_now ), [ 'a' => [ 'href' => [], 'class' => [], 'aria-label' => [], ], ] ); } /** * Checks compatibility with the current WPForms version. * * @since 1.9.0 * * @param string $required Minimum required WPForms version. * * @return bool True if a required version is compatible or empty, false if not. */ public static function is_wpforms_version_compatible( string $required ): bool { return empty( $required ) || version_compare( WPFORMS_VERSION, $required, '>=' ); } }
| ver. 1.1 | |
.
| PHP 8.3.30 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка