121 /** |
119 /** |
122 * Filters the tabs shown on the Plugin Install screen. |
120 * Filters the tabs shown on the Plugin Install screen. |
123 * |
121 * |
124 * @since 2.7.0 |
122 * @since 2.7.0 |
125 * |
123 * |
126 * @param array $tabs The tabs shown on the Plugin Install screen. Defaults include 'featured', 'popular', |
124 * @param string[] $tabs The tabs shown on the Plugin Install screen. Defaults include 'featured', 'popular', |
127 * 'recommended', 'favorites', and 'upload'. |
125 * 'recommended', 'favorites', and 'upload'. |
128 */ |
126 */ |
129 $tabs = apply_filters( 'install_plugins_tabs', $tabs ); |
127 $tabs = apply_filters( 'install_plugins_tabs', $tabs ); |
130 |
128 |
131 /** |
129 /** |
132 * Filters tabs not associated with a menu item on the Plugin Install screen. |
130 * Filters tabs not associated with a menu item on the Plugin Install screen. |
133 * |
131 * |
134 * @since 2.7.0 |
132 * @since 2.7.0 |
135 * |
133 * |
136 * @param array $nonmenu_tabs The tabs that don't have a Menu item on the Plugin Install screen. |
134 * @param string[] $nonmenu_tabs The tabs that don't have a menu item on the Plugin Install screen. |
137 */ |
135 */ |
138 $nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs ); |
136 $nonmenu_tabs = apply_filters( 'install_plugins_nonmenu_tabs', $nonmenu_tabs ); |
139 |
137 |
140 // If a non-valid menu tab has been selected, And it's not a non-menu action. |
138 // If a non-valid menu tab has been selected, And it's not a non-menu action. |
141 if ( empty( $tab ) || ( !isset( $tabs[ $tab ] ) && !in_array( $tab, (array) $nonmenu_tabs ) ) ) |
139 if ( empty( $tab ) || ( ! isset( $tabs[ $tab ] ) && ! in_array( $tab, (array) $nonmenu_tabs ) ) ) { |
142 $tab = key( $tabs ); |
140 $tab = key( $tabs ); |
|
141 } |
143 |
142 |
144 $installed_plugins = $this->get_installed_plugins(); |
143 $installed_plugins = $this->get_installed_plugins(); |
145 |
144 |
146 $args = array( |
145 $args = array( |
147 'page' => $paged, |
146 'page' => $paged, |
148 'per_page' => $per_page, |
147 'per_page' => $per_page, |
149 'fields' => array( |
148 // Send the locale to the API so it can provide context-sensitive results. |
150 'last_updated' => true, |
149 'locale' => get_user_locale(), |
151 'icons' => true, |
|
152 'active_installs' => true |
|
153 ), |
|
154 // Send the locale and installed plugin slugs to the API so it can provide context-sensitive results. |
|
155 'locale' => get_user_locale(), |
|
156 'installed_plugins' => array_keys( $installed_plugins ), |
|
157 ); |
150 ); |
158 |
151 |
159 switch ( $tab ) { |
152 switch ( $tab ) { |
160 case 'search': |
153 case 'search': |
161 $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; |
154 $type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term'; |
473 } |
491 } |
474 $title = wp_kses( $plugin['name'], $plugins_allowedtags ); |
492 $title = wp_kses( $plugin['name'], $plugins_allowedtags ); |
475 |
493 |
476 // Remove any HTML from the description. |
494 // Remove any HTML from the description. |
477 $description = strip_tags( $plugin['short_description'] ); |
495 $description = strip_tags( $plugin['short_description'] ); |
478 $version = wp_kses( $plugin['version'], $plugins_allowedtags ); |
496 $version = wp_kses( $plugin['version'], $plugins_allowedtags ); |
479 |
497 |
480 $name = strip_tags( $title . ' ' . $version ); |
498 $name = strip_tags( $title . ' ' . $version ); |
481 |
499 |
482 $author = wp_kses( $plugin['author'], $plugins_allowedtags ); |
500 $author = wp_kses( $plugin['author'], $plugins_allowedtags ); |
483 if ( ! empty( $author ) ) { |
501 if ( ! empty( $author ) ) { |
484 $author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>'; |
502 $author = ' <cite>' . sprintf( __( 'By %s' ), $author ) . '</cite>'; |
485 } |
503 } |
486 |
504 |
|
505 $requires_php = isset( $plugin['requires_php'] ) ? $plugin['requires_php'] : null; |
|
506 $requires_wp = isset( $plugin['requires'] ) ? $plugin['requires'] : null; |
|
507 |
|
508 $compatible_php = is_php_version_compatible( $requires_php ); |
|
509 $compatible_wp = is_wp_version_compatible( $requires_wp ); |
|
510 $tested_wp = ( empty( $plugin['tested'] ) || version_compare( get_bloginfo( 'version' ), $plugin['tested'], '<=' ) ); |
|
511 |
487 $action_links = array(); |
512 $action_links = array(); |
488 |
513 |
489 if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) { |
514 if ( current_user_can( 'install_plugins' ) || current_user_can( 'update_plugins' ) ) { |
490 $status = install_plugin_install_status( $plugin ); |
515 $status = install_plugin_install_status( $plugin ); |
491 |
516 |
492 switch ( $status['status'] ) { |
517 switch ( $status['status'] ) { |
493 case 'install': |
518 case 'install': |
494 if ( $status['url'] ) { |
519 if ( $status['url'] ) { |
495 /* translators: 1: Plugin name and version. */ |
520 if ( $compatible_php && $compatible_wp ) { |
496 $action_links[] = '<a class="install-now button" data-slug="' . esc_attr( $plugin['slug'] ) . '" href="' . esc_url( $status['url'] ) . '" aria-label="' . esc_attr( sprintf( __( 'Install %s now' ), $name ) ) . '" data-name="' . esc_attr( $name ) . '">' . __( 'Install Now' ) . '</a>'; |
521 $action_links[] = sprintf( |
|
522 '<a class="install-now button" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>', |
|
523 esc_attr( $plugin['slug'] ), |
|
524 esc_url( $status['url'] ), |
|
525 /* translators: %s: plugin name and version */ |
|
526 esc_attr( sprintf( __( 'Install %s now' ), $name ) ), |
|
527 esc_attr( $name ), |
|
528 __( 'Install Now' ) |
|
529 ); |
|
530 } else { |
|
531 $action_links[] = sprintf( |
|
532 '<button type="button" class="button button-disabled" disabled="disabled">%s</button>', |
|
533 _x( 'Cannot Install', 'plugin' ) |
|
534 ); |
|
535 } |
497 } |
536 } |
498 break; |
537 break; |
499 |
538 |
500 case 'update_available': |
539 case 'update_available': |
501 if ( $status['url'] ) { |
540 if ( $status['url'] ) { |
502 /* translators: 1: Plugin name and version */ |
541 if ( $compatible_php && $compatible_wp ) { |
503 $action_links[] = '<a class="update-now button aria-button-if-js" data-plugin="' . esc_attr( $status['file'] ) . '" data-slug="' . esc_attr( $plugin['slug'] ) . '" href="' . esc_url( $status['url'] ) . '" aria-label="' . esc_attr( sprintf( __( 'Update %s now' ), $name ) ) . '" data-name="' . esc_attr( $name ) . '">' . __( 'Update Now' ) . '</a>'; |
542 $action_links[] = sprintf( |
|
543 '<a class="update-now button aria-button-if-js" data-plugin="%s" data-slug="%s" href="%s" aria-label="%s" data-name="%s">%s</a>', |
|
544 esc_attr( $status['file'] ), |
|
545 esc_attr( $plugin['slug'] ), |
|
546 esc_url( $status['url'] ), |
|
547 /* translators: %s: plugin name and version */ |
|
548 esc_attr( sprintf( __( 'Update %s now' ), $name ) ), |
|
549 esc_attr( $name ), |
|
550 __( 'Update Now' ) |
|
551 ); |
|
552 } else { |
|
553 $action_links[] = sprintf( |
|
554 '<button type="button" class="button button-disabled" disabled="disabled">%s</button>', |
|
555 _x( 'Cannot Update', 'plugin' ) |
|
556 ); |
|
557 } |
504 } |
558 } |
505 break; |
559 break; |
506 |
560 |
507 case 'latest_installed': |
561 case 'latest_installed': |
508 case 'newer_installed': |
562 case 'newer_installed': |
509 if ( is_plugin_active( $status['file'] ) ) { |
563 if ( is_plugin_active( $status['file'] ) ) { |
510 $action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Active', 'plugin' ) . '</button>'; |
564 $action_links[] = sprintf( |
|
565 '<button type="button" class="button button-disabled" disabled="disabled">%s</button>', |
|
566 _x( 'Active', 'plugin' ) |
|
567 ); |
511 } elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) { |
568 } elseif ( current_user_can( 'activate_plugin', $status['file'] ) ) { |
512 $button_text = __( 'Activate' ); |
569 $button_text = __( 'Activate' ); |
513 /* translators: %s: Plugin name */ |
570 /* translators: %s: plugin name */ |
514 $button_label = _x( 'Activate %s', 'plugin' ); |
571 $button_label = _x( 'Activate %s', 'plugin' ); |
515 $activate_url = add_query_arg( array( |
572 $activate_url = add_query_arg( |
516 '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ), |
573 array( |
517 'action' => 'activate', |
574 '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $status['file'] ), |
518 'plugin' => $status['file'], |
575 'action' => 'activate', |
519 ), network_admin_url( 'plugins.php' ) ); |
576 'plugin' => $status['file'], |
|
577 ), |
|
578 network_admin_url( 'plugins.php' ) |
|
579 ); |
520 |
580 |
521 if ( is_network_admin() ) { |
581 if ( is_network_admin() ) { |
522 $button_text = __( 'Network Activate' ); |
582 $button_text = __( 'Network Activate' ); |
523 /* translators: %s: Plugin name */ |
583 /* translators: %s: plugin name */ |
524 $button_label = _x( 'Network Activate %s', 'plugin' ); |
584 $button_label = _x( 'Network Activate %s', 'plugin' ); |
525 $activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url ); |
585 $activate_url = add_query_arg( array( 'networkwide' => 1 ), $activate_url ); |
526 } |
586 } |
527 |
587 |
528 $action_links[] = sprintf( |
588 $action_links[] = sprintf( |
530 esc_url( $activate_url ), |
590 esc_url( $activate_url ), |
531 esc_attr( sprintf( $button_label, $plugin['name'] ) ), |
591 esc_attr( sprintf( $button_label, $plugin['name'] ) ), |
532 $button_text |
592 $button_text |
533 ); |
593 ); |
534 } else { |
594 } else { |
535 $action_links[] = '<button type="button" class="button button-disabled" disabled="disabled">' . _x( 'Installed', 'plugin' ) . '</button>'; |
595 $action_links[] = sprintf( |
|
596 '<button type="button" class="button button-disabled" disabled="disabled">%s</button>', |
|
597 _x( 'Installed', 'plugin' ) |
|
598 ); |
536 } |
599 } |
537 break; |
600 break; |
538 } |
601 } |
539 } |
602 } |
540 |
603 |
541 $details_link = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $plugin['slug'] . |
604 $details_link = self_admin_url( |
542 '&TB_iframe=true&width=600&height=550' ); |
605 'plugin-install.php?tab=plugin-information&plugin=' . $plugin['slug'] . |
543 |
606 '&TB_iframe=true&width=600&height=550' |
544 /* translators: 1: Plugin name and version. */ |
607 ); |
545 $action_links[] = '<a href="' . esc_url( $details_link ) . '" class="thickbox open-plugin-details-modal" aria-label="' . esc_attr( sprintf( __( 'More information about %s' ), $name ) ) . '" data-title="' . esc_attr( $name ) . '">' . __( 'More Details' ) . '</a>'; |
608 |
546 |
609 $action_links[] = sprintf( |
547 if ( !empty( $plugin['icons']['svg'] ) ) { |
610 '<a href="%s" class="thickbox open-plugin-details-modal" aria-label="%s" data-title="%s">%s</a>', |
|
611 esc_url( $details_link ), |
|
612 /* translators: %s: plugin name and version */ |
|
613 esc_attr( sprintf( __( 'More information about %s' ), $name ) ), |
|
614 esc_attr( $name ), |
|
615 __( 'More Details' ) |
|
616 ); |
|
617 |
|
618 if ( ! empty( $plugin['icons']['svg'] ) ) { |
548 $plugin_icon_url = $plugin['icons']['svg']; |
619 $plugin_icon_url = $plugin['icons']['svg']; |
549 } elseif ( !empty( $plugin['icons']['2x'] ) ) { |
620 } elseif ( ! empty( $plugin['icons']['2x'] ) ) { |
550 $plugin_icon_url = $plugin['icons']['2x']; |
621 $plugin_icon_url = $plugin['icons']['2x']; |
551 } elseif ( !empty( $plugin['icons']['1x'] ) ) { |
622 } elseif ( ! empty( $plugin['icons']['1x'] ) ) { |
552 $plugin_icon_url = $plugin['icons']['1x']; |
623 $plugin_icon_url = $plugin['icons']['1x']; |
553 } else { |
624 } else { |
554 $plugin_icon_url = $plugin['icons']['default']; |
625 $plugin_icon_url = $plugin['icons']['default']; |
555 } |
626 } |
556 |
627 |
557 /** |
628 /** |
558 * Filters the install action links for a plugin. |
629 * Filters the install action links for a plugin. |
559 * |
630 * |
560 * @since 2.7.0 |
631 * @since 2.7.0 |
561 * |
632 * |
562 * @param array $action_links An array of plugin action hyperlinks. Defaults are links to Details and Install Now. |
633 * @param string[] $action_links An array of plugin action links. Defaults are links to Details and Install Now. |
563 * @param array $plugin The plugin currently being listed. |
634 * @param array $plugin The plugin currently being listed. |
564 */ |
635 */ |
565 $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin ); |
636 $action_links = apply_filters( 'plugin_install_action_links', $action_links, $plugin ); |
566 |
637 |
567 $last_updated_timestamp = strtotime( $plugin['last_updated'] ); |
638 $last_updated_timestamp = strtotime( $plugin['last_updated'] ); |
568 ?> |
639 ?> |
569 <div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>"> |
640 <div class="plugin-card plugin-card-<?php echo sanitize_html_class( $plugin['slug'] ); ?>"> |
|
641 <?php |
|
642 if ( ! $compatible_php || ! $compatible_wp ) { |
|
643 echo '<div class="notice inline notice-error notice-alt"><p>'; |
|
644 if ( ! $compatible_php && ! $compatible_wp ) { |
|
645 _e( 'This plugin doesn’t work with your versions of WordPress and PHP.' ); |
|
646 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { |
|
647 printf( |
|
648 /* translators: 1: "Update WordPress" screen URL, 2: "Update PHP" page URL */ |
|
649 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ), |
|
650 self_admin_url( 'update-core.php' ), |
|
651 esc_url( wp_get_update_php_url() ) |
|
652 ); |
|
653 wp_update_php_annotation( '</p><p><em>', '</em>' ); |
|
654 } elseif ( current_user_can( 'update_core' ) ) { |
|
655 printf( |
|
656 /* translators: %s: "Update WordPress" screen URL */ |
|
657 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), |
|
658 self_admin_url( 'update-core.php' ) |
|
659 ); |
|
660 } elseif ( current_user_can( 'update_php' ) ) { |
|
661 printf( |
|
662 /* translators: %s: "Update PHP" page URL */ |
|
663 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), |
|
664 esc_url( wp_get_update_php_url() ) |
|
665 ); |
|
666 wp_update_php_annotation( '</p><p><em>', '</em>' ); |
|
667 } |
|
668 } elseif ( ! $compatible_wp ) { |
|
669 _e( 'This plugin doesn’t work with your version of WordPress.' ); |
|
670 if ( current_user_can( 'update_core' ) ) { |
|
671 printf( |
|
672 /* translators: %s: "Update WordPress" screen URL */ |
|
673 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), |
|
674 self_admin_url( 'update-core.php' ) |
|
675 ); |
|
676 } |
|
677 } elseif ( ! $compatible_php ) { |
|
678 _e( 'This plugin doesn’t work with your version of PHP.' ); |
|
679 if ( current_user_can( 'update_php' ) ) { |
|
680 printf( |
|
681 /* translators: %s: "Update PHP" page URL */ |
|
682 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), |
|
683 esc_url( wp_get_update_php_url() ) |
|
684 ); |
|
685 wp_update_php_annotation( '</p><p><em>', '</em>' ); |
|
686 } |
|
687 } |
|
688 echo '</p></div>'; |
|
689 } |
|
690 ?> |
570 <div class="plugin-card-top"> |
691 <div class="plugin-card-top"> |
571 <div class="name column-name"> |
692 <div class="name column-name"> |
572 <h3> |
693 <h3> |
573 <a href="<?php echo esc_url( $details_link ); ?>" class="thickbox open-plugin-details-modal"> |
694 <a href="<?php echo esc_url( $details_link ); ?>" class="thickbox open-plugin-details-modal"> |
574 <?php echo $title; ?> |
695 <?php echo $title; ?> |
575 <img src="<?php echo esc_attr( $plugin_icon_url ) ?>" class="plugin-icon" alt=""> |
696 <img src="<?php echo esc_attr( $plugin_icon_url ); ?>" class="plugin-icon" alt=""> |
576 </a> |
697 </a> |
577 </h3> |
698 </h3> |
578 </div> |
699 </div> |
579 <div class="action-links"> |
700 <div class="action-links"> |
580 <?php |
701 <?php |
581 if ( $action_links ) { |
702 if ( $action_links ) { |
582 echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>'; |
703 echo '<ul class="plugin-action-buttons"><li>' . implode( '</li><li>', $action_links ) . '</li></ul>'; |
583 } |
704 } |
584 ?> |
705 ?> |
585 </div> |
706 </div> |
586 <div class="desc column-description"> |
707 <div class="desc column-description"> |
587 <p><?php echo $description; ?></p> |
708 <p><?php echo $description; ?></p> |
588 <p class="authors"><?php echo $author; ?></p> |
709 <p class="authors"><?php echo $author; ?></p> |
589 </div> |
710 </div> |
590 </div> |
711 </div> |
591 <div class="plugin-card-bottom"> |
712 <div class="plugin-card-bottom"> |
592 <div class="vers column-rating"> |
713 <div class="vers column-rating"> |
593 <?php wp_star_rating( array( 'rating' => $plugin['rating'], 'type' => 'percent', 'number' => $plugin['num_ratings'] ) ); ?> |
714 <?php |
|
715 wp_star_rating( |
|
716 array( |
|
717 'rating' => $plugin['rating'], |
|
718 'type' => 'percent', |
|
719 'number' => $plugin['num_ratings'], |
|
720 ) |
|
721 ); |
|
722 ?> |
594 <span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n( $plugin['num_ratings'] ); ?>)</span> |
723 <span class="num-ratings" aria-hidden="true">(<?php echo number_format_i18n( $plugin['num_ratings'] ); ?>)</span> |
595 </div> |
724 </div> |
596 <div class="column-updated"> |
725 <div class="column-updated"> |
597 <strong><?php _e( 'Last Updated:' ); ?></strong> <?php printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) ); ?> |
726 <strong><?php _e( 'Last Updated:' ); ?></strong> <?php printf( __( '%s ago' ), human_time_diff( $last_updated_timestamp ) ); ?> |
598 </div> |
727 </div> |
599 <div class="column-downloaded"> |
728 <div class="column-downloaded"> |
600 <?php |
729 <?php |
601 if ( $plugin['active_installs'] >= 1000000 ) { |
730 if ( $plugin['active_installs'] >= 1000000 ) { |
602 $active_installs_text = _x( '1+ Million', 'Active plugin installations' ); |
731 $active_installs_millions = floor( $plugin['active_installs'] / 1000000 ); |
|
732 $active_installs_text = sprintf( |
|
733 _nx( '%s+ Million', '%s+ Million', $active_installs_millions, 'Active plugin installations' ), |
|
734 number_format_i18n( $active_installs_millions ) |
|
735 ); |
603 } elseif ( 0 == $plugin['active_installs'] ) { |
736 } elseif ( 0 == $plugin['active_installs'] ) { |
604 $active_installs_text = _x( 'Less Than 10', 'Active plugin installations' ); |
737 $active_installs_text = _x( 'Less Than 10', 'Active plugin installations' ); |
605 } else { |
738 } else { |
606 $active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+'; |
739 $active_installs_text = number_format_i18n( $plugin['active_installs'] ) . '+'; |
607 } |
740 } |
608 printf( __( '%s Active Installations' ), $active_installs_text ); |
741 printf( __( '%s Active Installations' ), $active_installs_text ); |
609 ?> |
742 ?> |
610 </div> |
743 </div> |
611 <div class="column-compatibility"> |
744 <div class="column-compatibility"> |
612 <?php |
745 <?php |
613 $wp_version = get_bloginfo( 'version' ); |
746 if ( ! $tested_wp ) { |
614 |
|
615 if ( ! empty( $plugin['tested'] ) && version_compare( substr( $wp_version, 0, strlen( $plugin['tested'] ) ), $plugin['tested'], '>' ) ) { |
|
616 echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>'; |
747 echo '<span class="compatibility-untested">' . __( 'Untested with your version of WordPress' ) . '</span>'; |
617 } elseif ( ! empty( $plugin['requires'] ) && version_compare( substr( $wp_version, 0, strlen( $plugin['requires'] ) ), $plugin['requires'], '<' ) ) { |
748 } elseif ( ! $compatible_wp ) { |
618 echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>'; |
749 echo '<span class="compatibility-incompatible">' . __( '<strong>Incompatible</strong> with your version of WordPress' ) . '</span>'; |
619 } else { |
750 } else { |
620 echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>'; |
751 echo '<span class="compatibility-compatible">' . __( '<strong>Compatible</strong> with your version of WordPress' ) . '</span>'; |
621 } |
752 } |
622 ?> |
753 ?> |
623 </div> |
754 </div> |
624 </div> |
755 </div> |
625 </div> |
756 </div> |
626 <?php |
757 <?php |
627 } |
758 } |
628 |
759 |
629 // Close off the group divs of the last one |
760 // Close off the group divs of the last one |
630 if ( ! empty( $group ) ) { |
761 if ( ! empty( $group ) ) { |
631 echo '</div></div>'; |
762 echo '</div></div>'; |