PK!/1|aa$themes/clenix/single-clenix_team.phpnu[
PK!5 5 themes/clenix/comments.phpnu[
1 && $clenix_comment_count != 0 ) { $clenix_comments_text .= esc_html__( 'Comments', 'clenix' ); } else if ( $clenix_comment_count == 0 ) { $clenix_comments_text .= esc_html__( 'Comment', 'clenix' ); } else { $clenix_comments_text .= esc_html__( 'Comment', 'clenix' ); } ?>

1 && get_option( 'page_comments' ) ) : // Are there comments to navigate through? ?>

'
', 'email' => '
', ); $clenix_args = array( 'class_submit' => 'submit btn-send ghost-on-hover-btn', 'submit_field' => '
%1$s %2$s
', 'comment_field' => '
', 'title_reply_before' => '

', 'title_reply_after' => '

', 'fields' => apply_filters( 'comment_form_default_fields', $clenix_fields ), ); ?>
PK!E`QQ(themes/clenix/sidebar-clenix_service.phpnu[
PK!Y4j7themes/clenix/wc-template-parts/content-shop-header.phpnu[
PK!; :themes/clenix/wc-template-parts/content-product-slider.phpnu[ array( 'items' => 1 ), '480' => array( 'items' => 2 ), '992' => array( 'items' => 2 ), ); } elseif ( ClenixTheme::$layout == 'full-width' ) { $responsive = array( '0' => array( 'items' => 1 ), '480' => array( 'items' => 2 ), '768' => array( 'items' => 3 ), '992' => array( 'items' => 4 ), ); } else { $responsive = array( '0' => array( 'items' => 1 ), '480' => array( 'items' => 2 ), '768' => array( 'items' => 2 ), '992' => array( 'items' => 3 ), ); } $loop = count( $products ) > $responsive['992']['items'] ? true : false; $owl_data = array( 'nav' => false, 'dots' => false, 'autoplay' => true, 'autoplayTimeout' => '5000', 'autoplaySpeed' => '200', 'autoplayHoverPause' => true, 'loop' => $loop, 'margin' => 30, 'responsive' => $responsive ); $owl_data = json_encode( $owl_data ); wp_enqueue_style( 'owl-carousel' ); wp_enqueue_style( 'owl-theme-default' ); wp_enqueue_script( 'owl-carousel' ); $wrapper_class = $type; if ( !$loop ) { $wrapper_class .= 'no-nav'; } ?> PK!U7themes/clenix/wc-template-parts/content-product-sku.phpnu[ get_sku() || $product->is_type( 'variable' ) ) ) : ?>
get_sku() ) ? $sku : esc_html__( 'N/A', 'clenix' ); ?>
  • '', 'already_in_wishslist_text' => '', 'product_added_text' => '', 'icon' => 'fa-heart-o', 'label' => '', 'link_classes' => 'add_to_wishlist single_add_to_wishlist alt wishlist-icon', ); ?>
PK!]٫!!4themes/clenix/wc-template-parts/content-shop-top.phpnu[
PK!z07themes/clenix/wc-template-parts/content-shop-footer.phpnu[
PK!OB8themes/clenix/wc-template-parts/content-product-meta.phpnu[ array( array( 'title' => esc_html__( 'Speed Optimization', 'metro' ), 'id' => 'rt_speed_optimization', 'icon' => 'el el-shopping-cart', 'subsections' => array( array( 'title' => esc_html__( 'Fonts Preload', 'metro' ), 'id' => 'rt_so_fonts_preload', 'subsection' => true, 'fields' => array( array( 'id' => 'rt_so_fonts_preload_csv', 'type' => 'textarea', 'title' => esc_html__( 'URL(s)', 'metro'), 'placeholder' => 'https://font-css-url/..., https://font-css-url/...', 'default' => ' http://localhost/wordpress/products/metro/wp-content/plugins/yith-woocommerce-wishlist/assets/css/font-awesome.css, http://localhost/wordpress/products/metro/wp-content/plugins/elementor/assets/lib/font-awesome/css/all.min.css, http://localhost/wordpress/products/metro/wp-content/plugins/elementor/assets/lib/font-awesome/css/v4-shims.min.css, http://localhost/wordpress/products/metro/wp-content/plugins/elementor/assets/lib/font-awesome/css/font-awesome.min.css ', ), ) ), ) ) ) ); class RTReduxFontPreloader{ public $option, $settings; function __construct($option, $settings){ $this->option = $option; $this->settings = $settings; $this->section(); // add_filter( 'style_loader_tag', array(&$this, 'preload_style'), 10, 4 ); add_filter( 'wp_head', array(&$this, 'preload_font'), 9); } function preload_font(){ $urls = array_map('trim', explode(',', ( ClenixTheme::$options['rt_so_fonts_preload_csv'] ) ) ); foreach($urls as $url) echo ""; } function section(){ foreach($this->settings['sections'] as $section){ $section_setting = array(); foreach($section as $key => $value){ if( $key == 'subsections' ) continue; $section_setting[$key] = $value; } Redux::setSection( $this->option, $section_setting ); $this->add_subsection($section['subsections']); } } function add_subsection($subsections){ foreach($subsections as $subsec){ Redux::setSection($this->option, $subsec); } } } new RTReduxFontPreloader('clenix', $optimization_settings); endif;PK!8+themes/clenix/lib/font-preload/__init__.phpnu[ jQuery( function ( $ ) { if ( ! ( window.Waypoint ) ) { // if Waypoint is not available, then we MUST remove our class from all elements because otherwise BGs will never show $('.elementor-section.lazyelementorbackgroundimages,.elementor-column-wrap.lazyelementorbackgroundimages').removeClass('lazyelementorbackgroundimages'); if ( window.console && console.warn ) { console.warn( 'Waypoint library is not loaded so backgrounds lazy loading is turned OFF' ); } return; } $('.lazyelementorbackgroundimages').each( function () { var $section = $( this ); new Waypoint({ element: $section.get( 0 ), handler: function( direction ) { //console.log( [ 'waypoint hit', $section.get( 0 ), $(window).scrollTop(), $section.offset() ] ); $section.removeClass('lazyelementorbackgroundimages'); }, offset: $(window).height()*1.5 // when item is within 1.5x the viewport size, start loading it }); } ); }); wp_version = $GLOBALS['wp_version']; // Announce that the class is ready, and pass the object (for advanced use). do_action_ref_array( 'tgmpa_init', array( $this ) ); // When the rest of WP has loaded, kick-start the rest of the class. add_action( 'init', array( $this, 'init' ) ); } /** * Magic method to (not) set protected properties from outside of this class. * * {@internal hackedihack... There is a serious bug in v2.3.2 - 2.3.6 where the `menu` property * is being assigned rather than tested in a conditional, effectively rendering it useless. * This 'hack' prevents this from happening.}} * * @see https://github.com/TGMPA/TGM-Plugin-Activation/blob/2.3.6/tgm-plugin-activation/class-tgm-plugin-activation.php#L1593 * * @since 2.5.2 * * @param string $name Name of an inaccessible property. * @param mixed $value Value to assign to the property. * @return void Silently fail to set the property when this is tried from outside of this class context. * (Inside this class context, the __set() method if not used as there is direct access.) */ public function __set( $name, $value ) { return; } /** * Magic method to get the value of a protected property outside of this class context. * * @since 2.5.2 * * @param string $name Name of an inaccessible property. * @return mixed The property value. */ public function __get( $name ) { return $this->{$name}; } /** * Initialise the interactions between this class and WordPress. * * Hooks in three new methods for the class: admin_menu, notices and styles. * * @since 2.0.0 * * @see TGM_Plugin_Activation::admin_menu() * @see TGM_Plugin_Activation::notices() * @see TGM_Plugin_Activation::styles() */ public function init() { /** * By default TGMPA only loads on the WP back-end and not in an Ajax call. Using this filter * you can overrule that behaviour. * * @since 2.5.0 * * @param bool $load Whether or not TGMPA should load. * Defaults to the return of `is_admin() && ! defined( 'DOING_AJAX' )`. */ if ( true !== apply_filters( 'tgmpa_load', ( is_admin() && ! defined( 'DOING_AJAX' ) ) ) ) { return; } // Load class strings. $this->strings = array( 'page_title' => esc_html__( 'Install Required Plugins', 'clenix' ), 'menu_title' => esc_html__( 'Install Plugins', 'clenix' ), /* translators: %s: plugin name. */ 'installing' => esc_html__( 'Installing Plugin: %s', 'clenix' ), /* translators: %s: plugin name. */ 'updating' => esc_html__( 'Updating Plugin: %s', 'clenix' ), 'oops' => esc_html__( 'Something went wrong with the plugin API.', 'clenix' ), 'notice_can_install_required' => _n_noop( /* translators: 1: plugin name(s). */ 'This theme requires the following plugin: %1$s.', 'This theme requires the following plugins: %1$s.', 'clenix' ), 'notice_can_install_recommended' => _n_noop( /* translators: 1: plugin name(s). */ 'This theme recommends the following plugin: %1$s.', 'This theme recommends the following plugins: %1$s.', 'clenix' ), 'notice_ask_to_update' => _n_noop( /* translators: 1: plugin name(s). */ 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.', 'clenix' ), 'notice_ask_to_update_maybe' => _n_noop( /* translators: 1: plugin name(s). */ 'There is an update available for: %1$s.', 'There are updates available for the following plugins: %1$s.', 'clenix' ), 'notice_can_activate_required' => _n_noop( /* translators: 1: plugin name(s). */ 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.', 'clenix' ), 'notice_can_activate_recommended' => _n_noop( /* translators: 1: plugin name(s). */ 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.', 'clenix' ), 'install_link' => _n_noop( 'Begin installing plugin', 'Begin installing plugins', 'clenix' ), 'update_link' => _n_noop( 'Begin updating plugin', 'Begin updating plugins', 'clenix' ), 'activate_link' => _n_noop( 'Begin activating plugin', 'Begin activating plugins', 'clenix' ), 'return' => esc_html__( 'Return to Required Plugins Installer', 'clenix' ), 'dashboard' => esc_html__( 'Return to the Dashboard', 'clenix' ), 'plugin_activated' => esc_html__( 'Plugin activated successfully.', 'clenix' ), 'activated_successfully' => esc_html__( 'The following plugin was activated successfully:', 'clenix' ), /* translators: 1: plugin name. */ 'plugin_already_active' => esc_html__( 'No action taken. Plugin %1$s was already active.', 'clenix' ), /* translators: 1: plugin name. */ 'plugin_needs_higher_version' => esc_html__( 'Plugin not activated. A higher version of %s is needed for this theme. Please update the plugin.', 'clenix' ), /* translators: 1: dashboard link. */ 'complete' => esc_html__( 'All plugins installed and activated successfully. %1$s', 'clenix' ), 'dismiss' => esc_html__( 'Dismiss this notice', 'clenix' ), 'notice_cannot_install_activate' => esc_html__( 'There are one or more required or recommended plugins to install, update or activate.', 'clenix' ), 'contact_admin' => esc_html__( 'Please contact the administrator of this site for help.', 'clenix' ), ); do_action( 'tgmpa_register' ); /* After this point, the plugins should be registered and the configuration set. */ // Proceed only if we have plugins to handle. if ( empty( $this->plugins ) || ! is_array( $this->plugins ) ) { return; } // Set up the menu and notices if we still have outstanding actions. if ( true !== $this->is_tgmpa_complete() ) { // Sort the plugins. array_multisort( $this->sort_order, SORT_ASC, $this->plugins ); add_action( 'admin_menu', array( $this, 'admin_menu' ) ); add_action( 'admin_head', array( $this, 'dismiss' ) ); // Prevent the normal links from showing underneath a single install/update page. add_filter( 'install_plugin_complete_actions', array( $this, 'actions' ) ); add_filter( 'update_plugin_complete_actions', array( $this, 'actions' ) ); if ( $this->has_notices ) { add_action( 'admin_notices', array( $this, 'notices' ) ); add_action( 'admin_init', array( $this, 'admin_init' ), 1 ); add_action( 'admin_enqueue_scripts', array( $this, 'thickbox' ) ); } } // If needed, filter plugin action links. add_action( 'load-plugins.php', array( $this, 'add_plugin_action_link_filters' ), 1 ); // Make sure things get reset on switch theme. add_action( 'switch_theme', array( $this, 'flush_plugins_cache' ) ); if ( $this->has_notices ) { add_action( 'switch_theme', array( $this, 'update_dismiss' ) ); } // Setup the force activation hook. if ( true === $this->has_forced_activation ) { add_action( 'admin_init', array( $this, 'force_activation' ) ); } // Setup the force deactivation hook. if ( true === $this->has_forced_deactivation ) { add_action( 'switch_theme', array( $this, 'force_deactivation' ) ); } } /** * Hook in plugin action link filters for the WP native plugins page. * * - Prevent activation of plugins which don't meet the minimum version requirements. * - Prevent deactivation of force-activated plugins. * - Add update notice if update available. * * @since 2.5.0 */ public function add_plugin_action_link_filters() { foreach ( $this->plugins as $slug => $plugin ) { if ( false === $this->can_plugin_activate( $slug ) ) { add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_activate' ), 20 ); } if ( true === $plugin['force_activation'] ) { add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_deactivate' ), 20 ); } if ( false !== $this->does_plugin_require_update( $slug ) ) { add_filter( 'plugin_action_links_' . $plugin['file_path'], array( $this, 'filter_plugin_action_links_update' ), 20 ); } } } /** * Remove the 'Activate' link on the WP native plugins page if the plugin does not meet the * minimum version requirements. * * @since 2.5.0 * * @param array $actions Action links. * @return array */ public function filter_plugin_action_links_activate( $actions ) { unset( $actions['activate'] ); return $actions; } /** * Remove the 'Deactivate' link on the WP native plugins page if the plugin has been set to force activate. * * @since 2.5.0 * * @param array $actions Action links. * @return array */ public function filter_plugin_action_links_deactivate( $actions ) { unset( $actions['deactivate'] ); return $actions; } /** * Add a 'Requires update' link on the WP native plugins page if the plugin does not meet the * minimum version requirements. * * @since 2.5.0 * * @param array $actions Action links. * @return array */ public function filter_plugin_action_links_update( $actions ) { $actions['update'] = sprintf( '%3$s', esc_url( $this->get_tgmpa_status_url( 'update' ) ), esc_attr__( 'This plugin needs to be updated to be compatible with your theme.', 'clenix' ), esc_html__( 'Update Required', 'clenix' ) ); return $actions; } /** * Handles calls to show plugin information via links in the notices. * * We get the links in the admin notices to point to the TGMPA page, rather * than the typical plugin-install.php file, so we can prepare everything * beforehand. * * WP does not make it easy to show the plugin information in the thickbox - * here we have to require a file that includes a function that does the * main work of displaying it, enqueue some styles, set up some globals and * finally call that function before exiting. * * Down right easy once you know how... * * Returns early if not the TGMPA page. * * @since 2.1.0 * * @global string $tab Used as iframe div class names, helps with styling * @global string $body_id Used as the iframe body ID, helps with styling * * @return null Returns early if not the TGMPA page. */ public function admin_init() { if ( ! $this->is_tgmpa_page() ) { return; } if ( isset( $_REQUEST['tab'] ) && 'plugin-information' === $_REQUEST['tab'] ) { // Needed for install_plugin_information(). require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; wp_enqueue_style( 'plugin-install' ); global $tab, $body_id; $body_id = 'plugin-information'; // @codingStandardsIgnoreStart $tab = 'plugin-information'; // @codingStandardsIgnoreEnd install_plugin_information(); exit; } } /** * Enqueue thickbox scripts/styles for plugin info. * * Thickbox is not automatically included on all admin pages, so we must * manually enqueue it for those pages. * * Thickbox is only loaded if the user has not dismissed the admin * notice or if there are any plugins left to install and activate. * * @since 2.1.0 */ public function thickbox() { if ( ! get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) ) { add_thickbox(); } } /** * Adds submenu page if there are plugin actions to take. * * This method adds the submenu page letting users know that a required * plugin needs to be installed. * * This page disappears once the plugin has been installed and activated. * * @since 1.0.0 * * @see TGM_Plugin_Activation::init() * @see TGM_Plugin_Activation::install_plugins_page() * * @return null Return early if user lacks capability to install a plugin. */ public function admin_menu() { // Make sure privileges are correct to see the page. if ( ! current_user_can( 'install_plugins' ) ) { return; } $args = apply_filters( 'tgmpa_admin_menu_args', array( 'parent_slug' => $this->parent_slug, // Parent Menu slug. 'page_title' => $this->strings['page_title'], // Page title. 'menu_title' => $this->strings['menu_title'], // Menu title. 'capability' => $this->capability, // Capability. 'menu_slug' => $this->menu, // Menu slug. 'function' => array( $this, 'install_plugins_page' ), // Callback. ) ); $this->add_admin_menu( $args ); } /** * Add the menu item. * * {@internal IMPORTANT! If this function changes, review the regex in the custom TGMPA * generator on the website.}} * * @since 2.5.0 * * @param array $args Menu item configuration. */ protected function add_admin_menu( array $args ) { $this->page_hook = add_theme_page( $args['page_title'], $args['menu_title'], $args['capability'], $args['menu_slug'], $args['function'] ); } /** * Echoes plugin installation form. * * This method is the callback for the admin_menu method function. * This displays the admin page and form area where the user can select to install and activate the plugin. * Aborts early if we're processing a plugin installation action. * * @since 1.0.0 * * @return null Aborts early if we're processing a plugin installation action. */ public function install_plugins_page() { // Store new instance of plugin table in object. $plugin_table = new TGMPA_List_Table; // Return early if processing a plugin installation action. if ( ( ( 'tgmpa-bulk-install' === $plugin_table->current_action() || 'tgmpa-bulk-update' === $plugin_table->current_action() ) && $plugin_table->process_bulk_actions() ) || $this->do_plugin_install() ) { return; } // Force refresh of available plugin information so we'll know about manual updates/deletes. wp_clean_plugins_cache( false ); ?>

prepare_items(); ?> message ) && is_string( $this->message ) ) { echo wp_kses( $this->message , 'alltext_allow' ); } ?> views(); ?>
display(); ?>
sanitize_key( urldecode( $_GET['plugin'] ) ); if ( ! isset( $this->plugins[ $slug ] ) ) { return false; } // Was an install or upgrade action link clicked? if ( ( isset( $_GET['tgmpa-install'] ) && 'install-plugin' === $_GET['tgmpa-install'] ) || ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) ) { $install_type = 'install'; if ( isset( $_GET['tgmpa-update'] ) && 'update-plugin' === $_GET['tgmpa-update'] ) { $install_type = 'update'; } check_admin_referer( 'tgmpa-' . $install_type, 'tgmpa-nonce' ); // Pass necessary information via URL if WP_Filesystem is needed. $url = wp_nonce_url( add_query_arg( array( 'plugin' => urlencode( $slug ), 'tgmpa-' . $install_type => $install_type . '-plugin', ), $this->get_tgmpa_url() ), 'tgmpa-' . $install_type, 'tgmpa-nonce' ); $method = ''; // Leave blank so WP_Filesystem can populate it as necessary. if ( false === ( $creds = request_filesystem_credentials( esc_url_raw( $url ), $method, false, false, array() ) ) ) { return true; } if ( ! WP_Filesystem( $creds ) ) { request_filesystem_credentials( esc_url_raw( $url ), $method, true, false, array() ); // Setup WP_Filesystem. return true; } /* If we arrive here, we have the filesystem. */ // Prep variables for Plugin_Installer_Skin class. $extra = array(); $extra['slug'] = $slug; // Needed for potentially renaming of directory name. $source = $this->get_download_url( $slug ); $api = ( 'repo' === $this->plugins[ $slug ]['source_type'] ) ? $this->get_plugins_api( $slug ) : null; $api = ( false !== $api ) ? $api : null; $url = add_query_arg( array( 'action' => $install_type . '-plugin', 'plugin' => urlencode( $slug ), ), 'update.php' ); if ( ! class_exists( 'Plugin_Upgrader', false ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; } $title = ( 'update' === $install_type ) ? $this->strings['updating'] : $this->strings['installing']; $skin_args = array( 'type' => ( 'bundled' !== $this->plugins[ $slug ]['source_type'] ) ? 'web' : 'upload', 'title' => sprintf( $title, $this->plugins[ $slug ]['name'] ), 'url' => esc_url_raw( $url ), 'nonce' => $install_type . '-plugin_' . $slug, 'plugin' => '', 'api' => $api, 'extra' => $extra, ); unset( $title ); if ( 'update' === $install_type ) { $skin_args['plugin'] = $this->plugins[ $slug ]['file_path']; $skin = new Plugin_Upgrader_Skin( $skin_args ); } else { $skin = new Plugin_Installer_Skin( $skin_args ); } // Create a new instance of Plugin_Upgrader. $upgrader = new Plugin_Upgrader( $skin ); // Perform the action and install the plugin from the $source urldecode(). add_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1, 3 ); if ( 'update' === $install_type ) { // Inject our info into the update transient. $to_inject = array( $slug => $this->plugins[ $slug ] ); $to_inject[ $slug ]['source'] = $source; $this->inject_update_info( $to_inject ); $upgrader->upgrade( $this->plugins[ $slug ]['file_path'] ); } else { $upgrader->install( $source ); } remove_filter( 'upgrader_source_selection', array( $this, 'maybe_adjust_source_dir' ), 1 ); // Make sure we have the correct file path now the plugin is installed/updated. $this->populate_file_path( $slug ); // Only activate plugins if the config option is set to true and the plugin isn't // already active (upgrade). if ( $this->is_automatic && ! $this->is_plugin_active( $slug ) ) { $plugin_activate = $upgrader->plugin_info(); // Grab the plugin info from the Plugin_Upgrader method. if ( false === $this->activate_single_plugin( $plugin_activate, $slug, true ) ) { return true; // Finish execution of the function early as we encountered an error. } } $this->show_tgmpa_version(); // Display message based on if all plugins are now active or not. if ( $this->is_tgmpa_complete() ) { echo '

', sprintf( esc_html( $this->strings['complete'] ), '' . esc_html__( 'Return to the Dashboard', 'clenix' ) . '' ), '

'; echo ''; } else { echo '

', esc_html( $this->strings['return'] ), '

'; } return true; } elseif ( isset( $this->plugins[ $slug ]['file_path'], $_GET['tgmpa-activate'] ) && 'activate-plugin' === $_GET['tgmpa-activate'] ) { // Activate action link was clicked. check_admin_referer( 'tgmpa-activate', 'tgmpa-nonce' ); if ( false === $this->activate_single_plugin( $this->plugins[ $slug ]['file_path'], $slug ) ) { return true; // Finish execution of the function early as we encountered an error. } } return false; } /** * Inject information into the 'update_plugins' site transient as WP checks that before running an update. * * @since 2.5.0 * * @param array $plugins The plugin information for the plugins which are to be updated. */ public function inject_update_info( $plugins ) { $repo_updates = get_site_transient( 'update_plugins' ); if ( ! is_object( $repo_updates ) ) { $repo_updates = new stdClass; } foreach ( $plugins as $slug => $plugin ) { $file_path = $plugin['file_path']; if ( empty( $repo_updates->response[ $file_path ] ) ) { $repo_updates->response[ $file_path ] = new stdClass; } // We only really need to set package, but let's do all we can in case WP changes something. $repo_updates->response[ $file_path ]->slug = $slug; $repo_updates->response[ $file_path ]->plugin = $file_path; $repo_updates->response[ $file_path ]->new_version = $plugin['version']; $repo_updates->response[ $file_path ]->package = $plugin['source']; if ( empty( $repo_updates->response[ $file_path ]->url ) && ! empty( $plugin['external_url'] ) ) { $repo_updates->response[ $file_path ]->url = $plugin['external_url']; } } set_site_transient( 'update_plugins', $repo_updates ); } /** * Adjust the plugin directory name if necessary. * * The final destination directory of a plugin is based on the subdirectory name found in the * (un)zipped source. In some cases - most notably GitHub repository plugin downloads -, this * subdirectory name is not the same as the expected slug and the plugin will not be recognized * as installed. This is fixed by adjusting the temporary unzipped source subdirectory name to * the expected plugin slug. * * @since 2.5.0 * * @param string $source Path to upgrade/zip-file-name.tmp/subdirectory/. * @param string $remote_source Path to upgrade/zip-file-name.tmp. * @param \WP_Upgrader $upgrader Instance of the upgrader which installs the plugin. * @return string $source */ public function maybe_adjust_source_dir( $source, $remote_source, $upgrader ) { if ( ! $this->is_tgmpa_page() || ! is_object( $GLOBALS['wp_filesystem'] ) ) { return $source; } // Check for single file plugins. $source_files = array_keys( $GLOBALS['wp_filesystem']->dirlist( $remote_source ) ); if ( 1 === count( $source_files ) && false === $GLOBALS['wp_filesystem']->is_dir( $source ) ) { return $source; } // Multi-file plugin, let's see if the directory is correctly named. $desired_slug = ''; // Figure out what the slug is supposed to be. if ( false === $upgrader->bulk && ! empty( $upgrader->skin->options['extra']['slug'] ) ) { $desired_slug = $upgrader->skin->options['extra']['slug']; } else { // Bulk installer contains less info, so fall back on the info registered here. foreach ( $this->plugins as $slug => $plugin ) { if ( ! empty( $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) && $plugin['name'] === $upgrader->skin->plugin_names[ $upgrader->skin->i ] ) { $desired_slug = $slug; break; } } unset( $slug, $plugin ); } if ( ! empty( $desired_slug ) ) { $subdir_name = untrailingslashit( str_replace( trailingslashit( $remote_source ), '', $source ) ); if ( ! empty( $subdir_name ) && $subdir_name !== $desired_slug ) { $from_path = untrailingslashit( $source ); $to_path = trailingslashit( $remote_source ) . $desired_slug; if ( true === $GLOBALS['wp_filesystem']->move( $from_path, $to_path ) ) { return trailingslashit( $to_path ); } else { return new WP_Error( 'rename_failed', esc_html__( 'The remote plugin package does not contain a folder with the desired slug and renaming did not work.', 'clenix' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'clenix' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) ); } } elseif ( empty( $subdir_name ) ) { return new WP_Error( 'packaged_wrong', esc_html__( 'The remote plugin package consists of more than one file, but the files are not packaged in a folder.', 'clenix' ) . ' ' . esc_html__( 'Please contact the plugin provider and ask them to package their plugin according to the WordPress guidelines.', 'clenix' ), array( 'found' => $subdir_name, 'expected' => $desired_slug ) ); } } return $source; } /** * Activate a single plugin and send feedback about the result to the screen. * * @since 2.5.0 * * @param string $file_path Path within wp-plugins/ to main plugin file. * @param string $slug Plugin slug. * @param bool $automatic Whether this is an automatic activation after an install. Defaults to false. * This determines the styling of the output messages. * @return bool False if an error was encountered, true otherwise. */ protected function activate_single_plugin( $file_path, $slug, $automatic = false ) { if ( $this->can_plugin_activate( $slug ) ) { $activate = activate_plugin( $file_path ); if ( is_wp_error( $activate ) ) { echo '

', wp_kses( $activate->get_error_message(), 'alltext_allow' ), '

', '

', esc_html( $this->strings['return'] ), '

'; return false; // End it here if there is an error with activation. } else { if ( ! $automatic ) { // Make sure message doesn't display again if bulk activation is performed // immediately after a single activation. if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK. echo '

', esc_html( $this->strings['activated_successfully'] ), ' ', esc_html( $this->plugins[ $slug ]['name'] ), '.

'; } } else { // Simpler message layout for use on the plugin install page. echo '

', esc_html( $this->strings['plugin_activated'] ), '

'; } } } elseif ( $this->is_plugin_active( $slug ) ) { // No simpler message format provided as this message should never be encountered // on the plugin install page. echo '

', sprintf( esc_html( $this->strings['plugin_already_active'] ), '' . esc_html( $this->plugins[ $slug ]['name'] ) . '' ), '

'; } elseif ( $this->does_plugin_require_update( $slug ) ) { if ( ! $automatic ) { // Make sure message doesn't display again if bulk activation is performed // immediately after a single activation. if ( ! isset( $_POST['action'] ) ) { // WPCS: CSRF OK. echo '

', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), '' . esc_html( $this->plugins[ $slug ]['name'] ) . '' ), '

'; } } else { // Simpler message layout for use on the plugin install page. echo '

', sprintf( esc_html( $this->strings['plugin_needs_higher_version'] ), esc_html( $this->plugins[ $slug ]['name'] ) ), '

'; } } return true; } /** * Echoes required plugin notice. * * Outputs a message telling users that a specific plugin is required for * their theme. If appropriate, it includes a link to the form page where * users can install and activate the plugin. * * Returns early if we're on the Install page. * * @since 1.0.0 * * @global object $current_screen * * @return null Returns early if we're on the Install page. */ public function notices() { // Remove nag on the install page / Return early if the nag message has been dismissed or user < author. if ( ( $this->is_tgmpa_page() || $this->is_core_update_page() ) || get_user_meta( get_current_user_id(), 'tgmpa_dismissed_notice_' . $this->id, true ) || ! current_user_can( apply_filters( 'tgmpa_show_admin_notice_capability', 'publish_posts' ) ) ) { return; } // Store for the plugin slugs by message type. $message = array(); // Initialize counters used to determine plurality of action link texts. $install_link_count = 0; $update_link_count = 0; $activate_link_count = 0; $total_required_action_count = 0; foreach ( $this->plugins as $slug => $plugin ) { if ( $this->is_plugin_active( $slug ) && false === $this->does_plugin_have_update( $slug ) ) { continue; } if ( ! $this->is_plugin_installed( $slug ) ) { if ( current_user_can( 'install_plugins' ) ) { $install_link_count++; if ( true === $plugin['required'] ) { $message['notice_can_install_required'][] = $slug; } else { $message['notice_can_install_recommended'][] = $slug; } } if ( true === $plugin['required'] ) { $total_required_action_count++; } } else { if ( ! $this->is_plugin_active( $slug ) && $this->can_plugin_activate( $slug ) ) { if ( current_user_can( 'activate_plugins' ) ) { $activate_link_count++; if ( true === $plugin['required'] ) { $message['notice_can_activate_required'][] = $slug; } else { $message['notice_can_activate_recommended'][] = $slug; } } if ( true === $plugin['required'] ) { $total_required_action_count++; } } if ( $this->does_plugin_require_update( $slug ) || false !== $this->does_plugin_have_update( $slug ) ) { if ( current_user_can( 'update_plugins' ) ) { $update_link_count++; if ( $this->does_plugin_require_update( $slug ) ) { $message['notice_ask_to_update'][] = $slug; } elseif ( false !== $this->does_plugin_have_update( $slug ) ) { $message['notice_ask_to_update_maybe'][] = $slug; } } if ( true === $plugin['required'] ) { $total_required_action_count++; } } } } unset( $slug, $plugin ); // If we have notices to display, we move forward. if ( ! empty( $message ) || $total_required_action_count > 0 ) { krsort( $message ); // Sort messages. $rendered = ''; // As add_settings_error() wraps the final message in a

and as the final message can't be // filtered, using

's in our html would render invalid html output. $line_template = '%s' . "\n"; if ( ! current_user_can( 'activate_plugins' ) && ! current_user_can( 'install_plugins' ) && ! current_user_can( 'update_plugins' ) ) { $rendered = esc_html( $this->strings['notice_cannot_install_activate'] ) . ' ' . esc_html( $this->strings['contact_admin'] ); $rendered .= $this->create_user_action_links_for_notice( 0, 0, 0, $line_template ); } else { // If dismissable is false and a message is set, output it now. if ( ! $this->dismissable && ! empty( $this->dismiss_msg ) ) { $rendered .= sprintf( $line_template, wp_kses( $this->dismiss_msg , 'alltext_allow' ) ); } // Render the individual message lines for the notice. foreach ( $message as $type => $plugin_group ) { $linked_plugins = array(); // Get the external info link for a plugin if one is available. foreach ( $plugin_group as $plugin_slug ) { $linked_plugins[] = $this->get_info_link( $plugin_slug ); } unset( $plugin_slug ); $count = count( $plugin_group ); $linked_plugins = array_map( array( 'TGMPA_Utils', 'wrap_in_em' ), $linked_plugins ); $last_plugin = array_pop( $linked_plugins ); // Pop off last name to prep for readability. $imploded = empty( $linked_plugins ) ? $last_plugin : ( implode( ', ', $linked_plugins ) . ' ' . esc_html_x( 'and', 'plugin A *and* plugin B', 'clenix' ) . ' ' . $last_plugin ); $rendered .= sprintf( $line_template, sprintf( translate_nooped_plural( $this->strings[ $type ], $count, 'clenix' ), $imploded, $count ) ); } unset( $type, $plugin_group, $linked_plugins, $count, $last_plugin, $imploded ); $rendered .= $this->create_user_action_links_for_notice( $install_link_count, $update_link_count, $activate_link_count, $line_template ); } // Register the nag messages and prepare them to be processed. add_settings_error( 'tgmpa', 'tgmpa', $rendered, $this->get_admin_notice_class() ); } // Admin options pages already output settings_errors, so this is to avoid duplication. if ( 'options-general' !== $GLOBALS['current_screen']->parent_base ) { $this->display_settings_errors(); } } /** * Generate the user action links for the admin notice. * * @since 2.6.0 * * @param int $install_count Number of plugins to install. * @param int $update_count Number of plugins to update. * @param int $activate_count Number of plugins to activate. * @param int $line_template Template for the HTML tag to output a line. * @return string Action links. */ protected function create_user_action_links_for_notice( $install_count, $update_count, $activate_count, $line_template ) { // Setup action links. $action_links = array( 'install' => '', 'update' => '', 'activate' => '', 'dismiss' => $this->dismissable ? '' . esc_html( $this->strings['dismiss'] ) . '' : '', ); $link_template = '%1$s'; if ( current_user_can( 'install_plugins' ) ) { if ( $install_count > 0 ) { $action_links['install'] = sprintf( $link_template, translate_nooped_plural( $this->strings['install_link'], $install_count, 'clenix' ), esc_url( $this->get_tgmpa_status_url( 'install' ) ) ); } if ( $update_count > 0 ) { $action_links['update'] = sprintf( $link_template, translate_nooped_plural(