441 if ( ! empty( $_REQUEST['order'] ) ) { |
451 if ( ! empty( $_REQUEST['order'] ) ) { |
442 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />'; |
452 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />'; |
443 } |
453 } |
444 ?> |
454 ?> |
445 <p class="search-box"> |
455 <p class="search-box"> |
446 <label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?>:</label> |
456 <label for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?></label> |
447 <input type="search" id="<?php echo esc_attr( $input_id ); ?>" class="wp-filter-search" name="s" value="<?php _admin_search_query(); ?>" placeholder="<?php esc_attr_e( 'Search installed plugins...' ); ?>" /> |
457 <input type="search" id="<?php echo esc_attr( $input_id ); ?>" class="wp-filter-search" name="s" value="<?php _admin_search_query(); ?>" /> |
448 <?php submit_button( $text, 'hide-if-js', '', false, array( 'id' => 'search-submit' ) ); ?> |
458 <?php submit_button( $text, 'hide-if-js', '', false, array( 'id' => 'search-submit' ) ); ?> |
449 </p> |
459 </p> |
450 <?php |
460 <?php |
451 } |
461 } |
452 |
462 |
453 /** |
463 /** |
454 * @global string $status |
464 * @global string $status |
455 * @return array |
465 * |
|
466 * @return string[] Array of column titles keyed by their column name. |
456 */ |
467 */ |
457 public function get_columns() { |
468 public function get_columns() { |
458 global $status; |
469 global $status; |
459 |
470 |
460 $columns = array( |
471 $columns = array( |
461 'cb' => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '', |
472 'cb' => ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ? '<input type="checkbox" />' : '', |
462 'name' => __( 'Plugin' ), |
473 'name' => __( 'Plugin' ), |
463 'description' => __( 'Description' ), |
474 'description' => __( 'Description' ), |
464 ); |
475 ); |
465 |
476 |
466 if ( $this->show_autoupdates ) { |
477 if ( $this->show_autoupdates && ! in_array( $status, array( 'mustuse', 'dropins' ), true ) ) { |
467 $columns['auto-updates'] = __( 'Automatic Updates' ); |
478 $columns['auto-updates'] = __( 'Automatic Updates' ); |
468 } |
479 } |
469 |
480 |
470 return $columns; |
481 return $columns; |
471 } |
482 } |
743 $requires_wp = isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : null; |
753 $requires_wp = isset( $plugin_data['RequiresWP'] ) ? $plugin_data['RequiresWP'] : null; |
744 |
754 |
745 $compatible_php = is_php_version_compatible( $requires_php ); |
755 $compatible_php = is_php_version_compatible( $requires_php ); |
746 $compatible_wp = is_wp_version_compatible( $requires_wp ); |
756 $compatible_wp = is_wp_version_compatible( $requires_wp ); |
747 |
757 |
|
758 $has_dependents = WP_Plugin_Dependencies::has_dependents( $plugin_file ); |
|
759 $has_active_dependents = WP_Plugin_Dependencies::has_active_dependents( $plugin_file ); |
|
760 $has_unmet_dependencies = WP_Plugin_Dependencies::has_unmet_dependencies( $plugin_file ); |
|
761 $has_circular_dependency = WP_Plugin_Dependencies::has_circular_dependency( $plugin_file ); |
|
762 |
748 if ( 'mustuse' === $context ) { |
763 if ( 'mustuse' === $context ) { |
749 $is_active = true; |
764 $is_active = true; |
750 } elseif ( 'dropins' === $context ) { |
765 } elseif ( 'dropins' === $context ) { |
751 $dropins = _get_dropins(); |
766 $dropins = _get_dropins(); |
752 $plugin_name = $plugin_file; |
767 $plugin_name = $plugin_file; |
753 |
768 |
754 if ( $plugin_file !== $plugin_data['Name'] ) { |
769 if ( $plugin_file !== $plugin_data['Name'] ) { |
755 $plugin_name .= '<br/>' . $plugin_data['Name']; |
770 $plugin_name .= '<br />' . $plugin_data['Name']; |
756 } |
771 } |
757 |
772 |
758 if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant. |
773 if ( true === ( $dropins[ $plugin_file ][1] ) ) { // Doesn't require a constant. |
759 $is_active = true; |
774 $is_active = true; |
760 $description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>'; |
775 $description = '<p><strong>' . $dropins[ $plugin_file ][0] . '</strong></p>'; |
785 } |
800 } |
786 |
801 |
787 if ( $screen->in_admin( 'network' ) ) { |
802 if ( $screen->in_admin( 'network' ) ) { |
788 if ( $is_active ) { |
803 if ( $is_active ) { |
789 if ( current_user_can( 'manage_network_plugins' ) ) { |
804 if ( current_user_can( 'manage_network_plugins' ) ) { |
790 $actions['deactivate'] = sprintf( |
805 if ( $has_active_dependents ) { |
791 '<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>', |
806 $actions['deactivate'] = __( 'Deactivate' ) . |
792 wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'deactivate-plugin_' . $plugin_file ), |
807 '<span class="screen-reader-text">' . |
793 esc_attr( $plugin_id_attr ), |
808 __( 'You cannot deactivate this plugin as other plugins require it.' ) . |
794 /* translators: %s: Plugin name. */ |
809 '</span>'; |
795 esc_attr( sprintf( _x( 'Network Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ), |
810 |
796 __( 'Network Deactivate' ) |
811 } else { |
797 ); |
812 $deactivate_url = 'plugins.php?action=deactivate' . |
|
813 '&plugin=' . urlencode( $plugin_file ) . |
|
814 '&plugin_status=' . $context . |
|
815 '&paged=' . $page . |
|
816 '&s=' . $s; |
|
817 |
|
818 $actions['deactivate'] = sprintf( |
|
819 '<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>', |
|
820 wp_nonce_url( $deactivate_url, 'deactivate-plugin_' . $plugin_file ), |
|
821 esc_attr( $plugin_id_attr ), |
|
822 /* translators: %s: Plugin name. */ |
|
823 esc_attr( sprintf( _x( 'Network Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ), |
|
824 _x( 'Network Deactivate', 'plugin' ) |
|
825 ); |
|
826 } |
798 } |
827 } |
799 } else { |
828 } else { |
800 if ( current_user_can( 'manage_network_plugins' ) ) { |
829 if ( current_user_can( 'manage_network_plugins' ) ) { |
801 if ( $compatible_php && $compatible_wp ) { |
830 if ( $compatible_php && $compatible_wp ) { |
802 $actions['activate'] = sprintf( |
831 if ( $has_unmet_dependencies ) { |
803 '<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>', |
832 $actions['activate'] = _x( 'Network Activate', 'plugin' ) . |
804 wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ), |
833 '<span class="screen-reader-text">' . |
805 esc_attr( $plugin_id_attr ), |
834 __( 'You cannot activate this plugin as it has unmet requirements.' ) . |
806 /* translators: %s: Plugin name. */ |
835 '</span>'; |
807 esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ), |
836 } else { |
808 __( 'Network Activate' ) |
837 $activate_url = 'plugins.php?action=activate' . |
809 ); |
838 '&plugin=' . urlencode( $plugin_file ) . |
|
839 '&plugin_status=' . $context . |
|
840 '&paged=' . $page . |
|
841 '&s=' . $s; |
|
842 |
|
843 $actions['activate'] = sprintf( |
|
844 '<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>', |
|
845 wp_nonce_url( $activate_url, 'activate-plugin_' . $plugin_file ), |
|
846 esc_attr( $plugin_id_attr ), |
|
847 /* translators: %s: Plugin name. */ |
|
848 esc_attr( sprintf( _x( 'Network Activate %s', 'plugin' ), $plugin_data['Name'] ) ), |
|
849 _x( 'Network Activate', 'plugin' ) |
|
850 ); |
|
851 } |
810 } else { |
852 } else { |
811 $actions['activate'] = sprintf( |
853 $actions['activate'] = sprintf( |
812 '<span>%s</span>', |
854 '<span>%s</span>', |
813 _x( 'Cannot Activate', 'plugin' ) |
855 _x( 'Cannot Activate', 'plugin' ) |
814 ); |
856 ); |
815 } |
857 } |
816 } |
858 } |
817 |
859 |
818 if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { |
860 if ( current_user_can( 'delete_plugins' ) && ! is_plugin_active( $plugin_file ) ) { |
819 $actions['delete'] = sprintf( |
861 if ( $has_dependents && ! $has_circular_dependency ) { |
820 '<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>', |
862 $actions['delete'] = __( 'Delete' ) . |
821 wp_nonce_url( 'plugins.php?action=delete-selected&checked[]=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'bulk-plugins' ), |
863 '<span class="screen-reader-text">' . |
822 esc_attr( $plugin_id_attr ), |
864 __( 'You cannot delete this plugin as other plugins require it.' ) . |
823 /* translators: %s: Plugin name. */ |
865 '</span>'; |
824 esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ), |
866 } else { |
825 __( 'Delete' ) |
867 $delete_url = 'plugins.php?action=delete-selected' . |
826 ); |
868 '&checked[]=' . urlencode( $plugin_file ) . |
|
869 '&plugin_status=' . $context . |
|
870 '&paged=' . $page . |
|
871 '&s=' . $s; |
|
872 |
|
873 $actions['delete'] = sprintf( |
|
874 '<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>', |
|
875 wp_nonce_url( $delete_url, 'bulk-plugins' ), |
|
876 esc_attr( $plugin_id_attr ), |
|
877 /* translators: %s: Plugin name. */ |
|
878 esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ), |
|
879 __( 'Delete' ) |
|
880 ); |
|
881 } |
827 } |
882 } |
828 } |
883 } |
829 } else { |
884 } else { |
830 if ( $restrict_network_active ) { |
885 if ( $restrict_network_active ) { |
831 $actions = array( |
886 $actions = array( |
835 $actions = array( |
890 $actions = array( |
836 'network_only' => __( 'Network Only' ), |
891 'network_only' => __( 'Network Only' ), |
837 ); |
892 ); |
838 } elseif ( $is_active ) { |
893 } elseif ( $is_active ) { |
839 if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) { |
894 if ( current_user_can( 'deactivate_plugin', $plugin_file ) ) { |
840 $actions['deactivate'] = sprintf( |
895 if ( $has_active_dependents ) { |
841 '<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>', |
896 $actions['deactivate'] = __( 'Deactivate' ) . |
842 wp_nonce_url( 'plugins.php?action=deactivate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'deactivate-plugin_' . $plugin_file ), |
897 '<span class="screen-reader-text">' . |
843 esc_attr( $plugin_id_attr ), |
898 __( 'You cannot deactivate this plugin as other plugins depend on it.' ) . |
844 /* translators: %s: Plugin name. */ |
899 '</span>'; |
845 esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ), |
900 } else { |
846 __( 'Deactivate' ) |
901 $deactivate_url = 'plugins.php?action=deactivate' . |
847 ); |
902 '&plugin=' . urlencode( $plugin_file ) . |
|
903 '&plugin_status=' . $context . |
|
904 '&paged=' . $page . |
|
905 '&s=' . $s; |
|
906 |
|
907 $actions['deactivate'] = sprintf( |
|
908 '<a href="%s" id="deactivate-%s" aria-label="%s">%s</a>', |
|
909 wp_nonce_url( $deactivate_url, 'deactivate-plugin_' . $plugin_file ), |
|
910 esc_attr( $plugin_id_attr ), |
|
911 /* translators: %s: Plugin name. */ |
|
912 esc_attr( sprintf( _x( 'Deactivate %s', 'plugin' ), $plugin_data['Name'] ) ), |
|
913 __( 'Deactivate' ) |
|
914 ); |
|
915 } |
848 } |
916 } |
849 |
917 |
850 if ( current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) { |
918 if ( current_user_can( 'resume_plugin', $plugin_file ) && is_plugin_paused( $plugin_file ) ) { |
|
919 $resume_url = 'plugins.php?action=resume' . |
|
920 '&plugin=' . urlencode( $plugin_file ) . |
|
921 '&plugin_status=' . $context . |
|
922 '&paged=' . $page . |
|
923 '&s=' . $s; |
|
924 |
851 $actions['resume'] = sprintf( |
925 $actions['resume'] = sprintf( |
852 '<a href="%s" id="resume-%s" class="resume-link" aria-label="%s">%s</a>', |
926 '<a href="%s" id="resume-%s" class="resume-link" aria-label="%s">%s</a>', |
853 wp_nonce_url( 'plugins.php?action=resume&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'resume-plugin_' . $plugin_file ), |
927 wp_nonce_url( $resume_url, 'resume-plugin_' . $plugin_file ), |
854 esc_attr( $plugin_id_attr ), |
928 esc_attr( $plugin_id_attr ), |
855 /* translators: %s: Plugin name. */ |
929 /* translators: %s: Plugin name. */ |
856 esc_attr( sprintf( _x( 'Resume %s', 'plugin' ), $plugin_data['Name'] ) ), |
930 esc_attr( sprintf( _x( 'Resume %s', 'plugin' ), $plugin_data['Name'] ) ), |
857 __( 'Resume' ) |
931 __( 'Resume' ) |
858 ); |
932 ); |
859 } |
933 } |
860 } else { |
934 } else { |
861 if ( current_user_can( 'activate_plugin', $plugin_file ) ) { |
935 if ( current_user_can( 'activate_plugin', $plugin_file ) ) { |
862 if ( $compatible_php && $compatible_wp ) { |
936 if ( $compatible_php && $compatible_wp ) { |
863 $actions['activate'] = sprintf( |
937 if ( $has_unmet_dependencies ) { |
864 '<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>', |
938 $actions['activate'] = _x( 'Activate', 'plugin' ) . |
865 wp_nonce_url( 'plugins.php?action=activate&plugin=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'activate-plugin_' . $plugin_file ), |
939 '<span class="screen-reader-text">' . |
866 esc_attr( $plugin_id_attr ), |
940 __( 'You cannot activate this plugin as it has unmet requirements.' ) . |
867 /* translators: %s: Plugin name. */ |
941 '</span>'; |
868 esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ), |
942 } else { |
869 __( 'Activate' ) |
943 $activate_url = 'plugins.php?action=activate' . |
870 ); |
944 '&plugin=' . urlencode( $plugin_file ) . |
|
945 '&plugin_status=' . $context . |
|
946 '&paged=' . $page . |
|
947 '&s=' . $s; |
|
948 |
|
949 $actions['activate'] = sprintf( |
|
950 '<a href="%s" id="activate-%s" class="edit" aria-label="%s">%s</a>', |
|
951 wp_nonce_url( $activate_url, 'activate-plugin_' . $plugin_file ), |
|
952 esc_attr( $plugin_id_attr ), |
|
953 /* translators: %s: Plugin name. */ |
|
954 esc_attr( sprintf( _x( 'Activate %s', 'plugin' ), $plugin_data['Name'] ) ), |
|
955 _x( 'Activate', 'plugin' ) |
|
956 ); |
|
957 } |
871 } else { |
958 } else { |
872 $actions['activate'] = sprintf( |
959 $actions['activate'] = sprintf( |
873 '<span>%s</span>', |
960 '<span>%s</span>', |
874 _x( 'Cannot Activate', 'plugin' ) |
961 _x( 'Cannot Activate', 'plugin' ) |
875 ); |
962 ); |
876 } |
963 } |
877 } |
964 } |
878 |
965 |
879 if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) { |
966 if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) { |
880 $actions['delete'] = sprintf( |
967 if ( $has_dependents && ! $has_circular_dependency ) { |
881 '<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>', |
968 $actions['delete'] = __( 'Delete' ) . |
882 wp_nonce_url( 'plugins.php?action=delete-selected&checked[]=' . urlencode( $plugin_file ) . '&plugin_status=' . $context . '&paged=' . $page . '&s=' . $s, 'bulk-plugins' ), |
969 '<span class="screen-reader-text">' . |
883 esc_attr( $plugin_id_attr ), |
970 __( 'You cannot delete this plugin as other plugins require it.' ) . |
884 /* translators: %s: Plugin name. */ |
971 '</span>'; |
885 esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ), |
972 } else { |
886 __( 'Delete' ) |
973 $delete_url = 'plugins.php?action=delete-selected' . |
887 ); |
974 '&checked[]=' . urlencode( $plugin_file ) . |
|
975 '&plugin_status=' . $context . |
|
976 '&paged=' . $page . |
|
977 '&s=' . $s; |
|
978 |
|
979 $actions['delete'] = sprintf( |
|
980 '<a href="%s" id="delete-%s" class="delete" aria-label="%s">%s</a>', |
|
981 wp_nonce_url( $delete_url, 'bulk-plugins' ), |
|
982 esc_attr( $plugin_id_attr ), |
|
983 /* translators: %s: Plugin name. */ |
|
984 esc_attr( sprintf( _x( 'Delete %s', 'plugin' ), $plugin_data['Name'] ) ), |
|
985 __( 'Delete' ) |
|
986 ); |
|
987 } |
888 } |
988 } |
889 } // End if $is_active. |
989 } // End if $is_active. |
890 } // End if $screen->in_admin( 'network' ). |
990 } // End if $screen->in_admin( 'network' ). |
891 } // End if $context. |
991 } // End if $context. |
892 |
992 |
900 * @since 3.1.0 |
1000 * @since 3.1.0 |
901 * |
1001 * |
902 * @param string[] $actions An array of plugin action links. By default this can include |
1002 * @param string[] $actions An array of plugin action links. By default this can include |
903 * 'activate', 'deactivate', and 'delete'. |
1003 * 'activate', 'deactivate', and 'delete'. |
904 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
1004 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
905 * @param array $plugin_data An array of plugin data. See `get_plugin_data()` |
1005 * @param array $plugin_data An array of plugin data. See get_plugin_data() |
906 * and the {@see 'plugin_row_meta'} filter for the list |
1006 * and the {@see 'plugin_row_meta'} filter for the list |
907 * of possible values. |
1007 * of possible values. |
908 * @param string $context The plugin context. By default this can include 'all', |
1008 * @param string $context The plugin context. By default this can include 'all', |
909 * 'active', 'inactive', 'recently_activated', 'upgrade', |
1009 * 'active', 'inactive', 'recently_activated', 'upgrade', |
910 * 'mustuse', 'dropins', and 'search'. |
1010 * 'mustuse', 'dropins', and 'search'. |
920 * @since 3.1.0 |
1020 * @since 3.1.0 |
921 * |
1021 * |
922 * @param string[] $actions An array of plugin action links. By default this can include |
1022 * @param string[] $actions An array of plugin action links. By default this can include |
923 * 'activate', 'deactivate', and 'delete'. |
1023 * 'activate', 'deactivate', and 'delete'. |
924 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
1024 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
925 * @param array $plugin_data An array of plugin data. See `get_plugin_data()` |
1025 * @param array $plugin_data An array of plugin data. See get_plugin_data() |
926 * and the {@see 'plugin_row_meta'} filter for the list |
1026 * and the {@see 'plugin_row_meta'} filter for the list |
927 * of possible values. |
1027 * of possible values. |
928 * @param string $context The plugin context. By default this can include 'all', |
1028 * @param string $context The plugin context. By default this can include 'all', |
929 * 'active', 'inactive', 'recently_activated', 'upgrade', |
1029 * 'active', 'inactive', 'recently_activated', 'upgrade', |
930 * 'mustuse', 'dropins', and 'search'. |
1030 * 'mustuse', 'dropins', and 'search'. |
942 * |
1042 * |
943 * @param string[] $actions An array of plugin action links. By default this can include |
1043 * @param string[] $actions An array of plugin action links. By default this can include |
944 * 'activate', 'deactivate', and 'delete'. With Multisite active |
1044 * 'activate', 'deactivate', and 'delete'. With Multisite active |
945 * this can also include 'network_active' and 'network_only' items. |
1045 * this can also include 'network_active' and 'network_only' items. |
946 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
1046 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
947 * @param array $plugin_data An array of plugin data. See `get_plugin_data()` |
1047 * @param array $plugin_data An array of plugin data. See get_plugin_data() |
948 * and the {@see 'plugin_row_meta'} filter for the list |
1048 * and the {@see 'plugin_row_meta'} filter for the list |
949 * of possible values. |
1049 * of possible values. |
950 * @param string $context The plugin context. By default this can include 'all', |
1050 * @param string $context The plugin context. By default this can include 'all', |
951 * 'active', 'inactive', 'recently_activated', 'upgrade', |
1051 * 'active', 'inactive', 'recently_activated', 'upgrade', |
952 * 'mustuse', 'dropins', and 'search'. |
1052 * 'mustuse', 'dropins', and 'search'. |
964 * |
1064 * |
965 * @param string[] $actions An array of plugin action links. By default this can include |
1065 * @param string[] $actions An array of plugin action links. By default this can include |
966 * 'activate', 'deactivate', and 'delete'. With Multisite active |
1066 * 'activate', 'deactivate', and 'delete'. With Multisite active |
967 * this can also include 'network_active' and 'network_only' items. |
1067 * this can also include 'network_active' and 'network_only' items. |
968 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
1068 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
969 * @param array $plugin_data An array of plugin data. See `get_plugin_data()` |
1069 * @param array $plugin_data An array of plugin data. See get_plugin_data() |
970 * and the {@see 'plugin_row_meta'} filter for the list |
1070 * and the {@see 'plugin_row_meta'} filter for the list |
971 * of possible values. |
1071 * of possible values. |
972 * @param string $context The plugin context. By default this can include 'all', |
1072 * @param string $context The plugin context. By default this can include 'all', |
973 * 'active', 'inactive', 'recently_activated', 'upgrade', |
1073 * 'active', 'inactive', 'recently_activated', 'upgrade', |
974 * 'mustuse', 'dropins', and 'search'. |
1074 * 'mustuse', 'dropins', and 'search'. |
977 |
1077 |
978 } |
1078 } |
979 |
1079 |
980 $class = $is_active ? 'active' : 'inactive'; |
1080 $class = $is_active ? 'active' : 'inactive'; |
981 $checkbox_id = 'checkbox_' . md5( $plugin_file ); |
1081 $checkbox_id = 'checkbox_' . md5( $plugin_file ); |
982 |
1082 $disabled = ''; |
983 if ( $restrict_network_active || $restrict_network_only || in_array( $status, array( 'mustuse', 'dropins' ), true ) || ! $compatible_php ) { |
1083 |
|
1084 if ( $has_dependents || $has_unmet_dependencies ) { |
|
1085 $disabled = 'disabled'; |
|
1086 } |
|
1087 |
|
1088 if ( |
|
1089 $restrict_network_active || |
|
1090 $restrict_network_only || |
|
1091 in_array( $status, array( 'mustuse', 'dropins' ), true ) || |
|
1092 ! $compatible_php |
|
1093 ) { |
984 $checkbox = ''; |
1094 $checkbox = ''; |
985 } else { |
1095 } else { |
986 $checkbox = sprintf( |
1096 $checkbox = sprintf( |
987 '<label class="screen-reader-text" for="%1$s">%2$s</label>' . |
1097 '<label class="label-covers-full-cell" for="%1$s">' . |
988 '<input type="checkbox" name="checked[]" value="%3$s" id="%1$s" />', |
1098 '<span class="screen-reader-text">%2$s</span></label>' . |
|
1099 '<input type="checkbox" name="checked[]" value="%3$s" id="%1$s" ' . $disabled . '/>', |
989 $checkbox_id, |
1100 $checkbox_id, |
990 /* translators: %s: Plugin name. */ |
1101 /* translators: Hidden accessibility text. %s: Plugin name. */ |
991 sprintf( __( 'Select %s' ), $plugin_data['Name'] ), |
1102 sprintf( __( 'Select %s' ), $plugin_data['Name'] ), |
992 esc_attr( $plugin_file ) |
1103 esc_attr( $plugin_file ) |
993 ); |
1104 ); |
994 } |
1105 } |
995 |
1106 |
996 if ( 'dropins' !== $context ) { |
1107 if ( 'dropins' !== $context ) { |
997 $description = '<p>' . ( $plugin_data['Description'] ? $plugin_data['Description'] : ' ' ) . '</p>'; |
1108 $description = '<p>' . ( $plugin_data['Description'] ? $plugin_data['Description'] : ' ' ) . '</p>'; |
998 $plugin_name = $plugin_data['Name']; |
1109 $plugin_name = $plugin_data['Name']; |
999 } |
1110 } |
1000 |
1111 |
1001 if ( ! empty( $totals['upgrade'] ) && ! empty( $plugin_data['update'] ) |
1112 if ( |
1002 || ! $compatible_php || ! $compatible_wp |
1113 ! empty( $totals['upgrade'] ) && |
|
1114 ! empty( $plugin_data['update'] ) || |
|
1115 ! $compatible_php || |
|
1116 ! $compatible_wp |
1003 ) { |
1117 ) { |
1004 $class .= ' update'; |
1118 $class .= ' update'; |
1005 } |
1119 } |
1006 |
1120 |
1007 $paused = ! $screen->in_admin( 'network' ) && is_plugin_paused( $plugin_file ); |
1121 $paused = ! $screen->in_admin( 'network' ) && is_plugin_paused( $plugin_file ); |
1047 echo "<td class='$classes{$extra_classes}'> |
1160 echo "<td class='$classes{$extra_classes}'> |
1048 <div class='plugin-description'>$description</div> |
1161 <div class='plugin-description'>$description</div> |
1049 <div class='$class second plugin-version-author-uri'>"; |
1162 <div class='$class second plugin-version-author-uri'>"; |
1050 |
1163 |
1051 $plugin_meta = array(); |
1164 $plugin_meta = array(); |
|
1165 |
1052 if ( ! empty( $plugin_data['Version'] ) ) { |
1166 if ( ! empty( $plugin_data['Version'] ) ) { |
1053 /* translators: %s: Plugin version number. */ |
1167 /* translators: %s: Plugin version number. */ |
1054 $plugin_meta[] = sprintf( __( 'Version %s' ), $plugin_data['Version'] ); |
1168 $plugin_meta[] = sprintf( __( 'Version %s' ), $plugin_data['Version'] ); |
1055 } |
1169 } |
|
1170 |
1056 if ( ! empty( $plugin_data['Author'] ) ) { |
1171 if ( ! empty( $plugin_data['Author'] ) ) { |
1057 $author = $plugin_data['Author']; |
1172 $author = $plugin_data['Author']; |
|
1173 |
1058 if ( ! empty( $plugin_data['AuthorURI'] ) ) { |
1174 if ( ! empty( $plugin_data['AuthorURI'] ) ) { |
1059 $author = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>'; |
1175 $author = '<a href="' . $plugin_data['AuthorURI'] . '">' . $plugin_data['Author'] . '</a>'; |
1060 } |
1176 } |
|
1177 |
1061 /* translators: %s: Plugin author name. */ |
1178 /* translators: %s: Plugin author name. */ |
1062 $plugin_meta[] = sprintf( __( 'By %s' ), $author ); |
1179 $plugin_meta[] = sprintf( __( 'By %s' ), $author ); |
1063 } |
1180 } |
1064 |
1181 |
1065 // Details link using API info, if available. |
1182 // Details link using API info, if available. |
1263 |
1405 |
1264 echo '</tr>'; |
1406 echo '</tr>'; |
1265 |
1407 |
1266 if ( ! $compatible_php || ! $compatible_wp ) { |
1408 if ( ! $compatible_php || ! $compatible_wp ) { |
1267 printf( |
1409 printf( |
1268 '<tr class="plugin-update-tr">' . |
1410 '<tr class="plugin-update-tr"><td colspan="%s" class="plugin-update colspanchange">', |
1269 '<td colspan="%s" class="plugin-update colspanchange">' . |
|
1270 '<div class="update-message notice inline notice-error notice-alt"><p>', |
|
1271 esc_attr( $this->get_column_count() ) |
1411 esc_attr( $this->get_column_count() ) |
1272 ); |
1412 ); |
1273 |
1413 |
|
1414 $incompatible_message = ''; |
1274 if ( ! $compatible_php && ! $compatible_wp ) { |
1415 if ( ! $compatible_php && ! $compatible_wp ) { |
1275 _e( 'This plugin does not work with your versions of WordPress and PHP.' ); |
1416 $incompatible_message .= __( 'This plugin does not work with your versions of WordPress and PHP.' ); |
1276 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { |
1417 if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { |
1277 printf( |
1418 $incompatible_message .= sprintf( |
1278 /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */ |
1419 /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */ |
1279 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ), |
1420 ' ' . __( '<a href="%1$s">Please update WordPress</a>, and then <a href="%2$s">learn more about updating PHP</a>.' ), |
1280 self_admin_url( 'update-core.php' ), |
1421 self_admin_url( 'update-core.php' ), |
1281 esc_url( wp_get_update_php_url() ) |
1422 esc_url( wp_get_update_php_url() ) |
1282 ); |
1423 ); |
1283 wp_update_php_annotation( '</p><p><em>', '</em>' ); |
1424 $incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false ); |
1284 } elseif ( current_user_can( 'update_core' ) ) { |
1425 } elseif ( current_user_can( 'update_core' ) ) { |
1285 printf( |
1426 $incompatible_message .= sprintf( |
1286 /* translators: %s: URL to WordPress Updates screen. */ |
1427 /* translators: %s: URL to WordPress Updates screen. */ |
1287 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), |
1428 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), |
1288 self_admin_url( 'update-core.php' ) |
1429 self_admin_url( 'update-core.php' ) |
1289 ); |
1430 ); |
1290 } elseif ( current_user_can( 'update_php' ) ) { |
1431 } elseif ( current_user_can( 'update_php' ) ) { |
1291 printf( |
1432 $incompatible_message .= sprintf( |
1292 /* translators: %s: URL to Update PHP page. */ |
1433 /* translators: %s: URL to Update PHP page. */ |
1293 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), |
1434 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), |
1294 esc_url( wp_get_update_php_url() ) |
1435 esc_url( wp_get_update_php_url() ) |
1295 ); |
1436 ); |
1296 wp_update_php_annotation( '</p><p><em>', '</em>' ); |
1437 $incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false ); |
1297 } |
1438 } |
1298 } elseif ( ! $compatible_wp ) { |
1439 } elseif ( ! $compatible_wp ) { |
1299 _e( 'This plugin does not work with your version of WordPress.' ); |
1440 $incompatible_message .= __( 'This plugin does not work with your version of WordPress.' ); |
1300 if ( current_user_can( 'update_core' ) ) { |
1441 if ( current_user_can( 'update_core' ) ) { |
1301 printf( |
1442 $incompatible_message .= sprintf( |
1302 /* translators: %s: URL to WordPress Updates screen. */ |
1443 /* translators: %s: URL to WordPress Updates screen. */ |
1303 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), |
1444 ' ' . __( '<a href="%s">Please update WordPress</a>.' ), |
1304 self_admin_url( 'update-core.php' ) |
1445 self_admin_url( 'update-core.php' ) |
1305 ); |
1446 ); |
1306 } |
1447 } |
1307 } elseif ( ! $compatible_php ) { |
1448 } elseif ( ! $compatible_php ) { |
1308 _e( 'This plugin does not work with your version of PHP.' ); |
1449 $incompatible_message .= __( 'This plugin does not work with your version of PHP.' ); |
1309 if ( current_user_can( 'update_php' ) ) { |
1450 if ( current_user_can( 'update_php' ) ) { |
1310 printf( |
1451 $incompatible_message .= sprintf( |
1311 /* translators: %s: URL to Update PHP page. */ |
1452 /* translators: %s: URL to Update PHP page. */ |
1312 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), |
1453 ' ' . __( '<a href="%s">Learn more about updating PHP</a>.' ), |
1313 esc_url( wp_get_update_php_url() ) |
1454 esc_url( wp_get_update_php_url() ) |
1314 ); |
1455 ); |
1315 wp_update_php_annotation( '</p><p><em>', '</em>' ); |
1456 $incompatible_message .= wp_update_php_annotation( '</p><p><em>', '</em>', false ); |
1316 } |
1457 } |
1317 } |
1458 } |
1318 |
1459 |
1319 echo '</p></div></td></tr>'; |
1460 wp_admin_notice( |
|
1461 $incompatible_message, |
|
1462 array( |
|
1463 'type' => 'error', |
|
1464 'additional_classes' => array( 'notice-alt', 'inline', 'update-message' ), |
|
1465 ) |
|
1466 ); |
|
1467 |
|
1468 echo '</td></tr>'; |
1320 } |
1469 } |
1321 |
1470 |
1322 /** |
1471 /** |
1323 * Fires after each row in the Plugins list table. |
1472 * Fires after each row in the Plugins list table. |
1324 * |
1473 * |
1325 * @since 2.3.0 |
1474 * @since 2.3.0 |
1326 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled' |
1475 * @since 5.5.0 Added 'auto-update-enabled' and 'auto-update-disabled' |
1327 * to possible values for `$status`. |
1476 * to possible values for `$status`. |
1328 * |
1477 * |
1329 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
1478 * @param string $plugin_file Path to the plugin file relative to the plugins directory. |
1330 * @param array $plugin_data An array of plugin data. See `get_plugin_data()` |
1479 * @param array $plugin_data An array of plugin data. See get_plugin_data() |
1331 * and the {@see 'plugin_row_meta'} filter for the list |
1480 * and the {@see 'plugin_row_meta'} filter for the list |
1332 * of possible values. |
1481 * of possible values. |
1333 * @param string $status Status filter currently applied to the plugin list. |
1482 * @param string $status Status filter currently applied to the plugin list. |
1334 * Possible values are: 'all', 'active', 'inactive', |
1483 * Possible values are: 'all', 'active', 'inactive', |
1335 * 'recently_activated', 'upgrade', 'mustuse', 'dropins', |
1484 * 'recently_activated', 'upgrade', 'mustuse', 'dropins', |
1367 * @return string Unalterable name for the primary column, in this case, 'name'. |
1516 * @return string Unalterable name for the primary column, in this case, 'name'. |
1368 */ |
1517 */ |
1369 protected function get_primary_column_name() { |
1518 protected function get_primary_column_name() { |
1370 return 'name'; |
1519 return 'name'; |
1371 } |
1520 } |
|
1521 |
|
1522 /** |
|
1523 * Prints a list of other plugins that depend on the plugin. |
|
1524 * |
|
1525 * @since 6.5.0 |
|
1526 * |
|
1527 * @param string $dependency The dependency's filepath, relative to the plugins directory. |
|
1528 */ |
|
1529 protected function add_dependents_to_dependency_plugin_row( $dependency ) { |
|
1530 $dependent_names = WP_Plugin_Dependencies::get_dependent_names( $dependency ); |
|
1531 |
|
1532 if ( empty( $dependent_names ) ) { |
|
1533 return; |
|
1534 } |
|
1535 |
|
1536 $dependency_note = __( 'Note: This plugin cannot be deactivated or deleted until the plugins that require it are deactivated or deleted.' ); |
|
1537 |
|
1538 $comma = wp_get_list_item_separator(); |
|
1539 $required_by = sprintf( |
|
1540 /* translators: %s: List of dependencies. */ |
|
1541 __( '<strong>Required by:</strong> %s' ), |
|
1542 implode( $comma, $dependent_names ) |
|
1543 ); |
|
1544 |
|
1545 printf( |
|
1546 '<div class="required-by"><p>%1$s</p><p>%2$s</p></div>', |
|
1547 $required_by, |
|
1548 $dependency_note |
|
1549 ); |
|
1550 } |
|
1551 |
|
1552 /** |
|
1553 * Prints a list of other plugins that the plugin depends on. |
|
1554 * |
|
1555 * @since 6.5.0 |
|
1556 * |
|
1557 * @param string $dependent The dependent plugin's filepath, relative to the plugins directory. |
|
1558 */ |
|
1559 protected function add_dependencies_to_dependent_plugin_row( $dependent ) { |
|
1560 $dependency_names = WP_Plugin_Dependencies::get_dependency_names( $dependent ); |
|
1561 |
|
1562 if ( array() === $dependency_names ) { |
|
1563 return; |
|
1564 } |
|
1565 |
|
1566 $links = array(); |
|
1567 foreach ( $dependency_names as $slug => $name ) { |
|
1568 $links[] = $this->get_dependency_view_details_link( $name, $slug ); |
|
1569 } |
|
1570 |
|
1571 $is_active = is_multisite() ? is_plugin_active_for_network( $dependent ) : is_plugin_active( $dependent ); |
|
1572 $comma = wp_get_list_item_separator(); |
|
1573 $requires = sprintf( |
|
1574 /* translators: %s: List of dependency names. */ |
|
1575 __( '<strong>Requires:</strong> %s' ), |
|
1576 implode( $comma, $links ) |
|
1577 ); |
|
1578 |
|
1579 $notice = ''; |
|
1580 $error_message = ''; |
|
1581 if ( WP_Plugin_Dependencies::has_unmet_dependencies( $dependent ) ) { |
|
1582 if ( $is_active ) { |
|
1583 $error_message = __( 'This plugin is active but may not function correctly because required plugins are missing or inactive.' ); |
|
1584 } else { |
|
1585 $error_message = __( 'This plugin cannot be activated because required plugins are missing or inactive.' ); |
|
1586 } |
|
1587 $notice = wp_get_admin_notice( |
|
1588 $error_message, |
|
1589 array( |
|
1590 'type' => 'error', |
|
1591 'additional_classes' => array( 'inline', 'notice-alt' ), |
|
1592 ) |
|
1593 ); |
|
1594 } |
|
1595 |
|
1596 printf( |
|
1597 '<div class="requires"><p>%1$s</p><p>%2$s</p></div>', |
|
1598 $requires, |
|
1599 $notice |
|
1600 ); |
|
1601 } |
|
1602 |
|
1603 /** |
|
1604 * Returns a 'View details' like link for a dependency. |
|
1605 * |
|
1606 * @since 6.5.0 |
|
1607 * |
|
1608 * @param string $name The dependency's name. |
|
1609 * @param string $slug The dependency's slug. |
|
1610 * @return string A 'View details' link for the dependency. |
|
1611 */ |
|
1612 protected function get_dependency_view_details_link( $name, $slug ) { |
|
1613 $dependency_data = WP_Plugin_Dependencies::get_dependency_data( $slug ); |
|
1614 |
|
1615 if ( false === $dependency_data |
|
1616 || $name === $slug |
|
1617 || $name !== $dependency_data['name'] |
|
1618 || empty( $dependency_data['version'] ) |
|
1619 ) { |
|
1620 return $name; |
|
1621 } |
|
1622 |
|
1623 return $this->get_view_details_link( $name, $slug ); |
|
1624 } |
|
1625 |
|
1626 /** |
|
1627 * Returns a 'View details' link for the plugin. |
|
1628 * |
|
1629 * @since 6.5.0 |
|
1630 * |
|
1631 * @param string $name The plugin's name. |
|
1632 * @param string $slug The plugin's slug. |
|
1633 * @return string A 'View details' link for the plugin. |
|
1634 */ |
|
1635 protected function get_view_details_link( $name, $slug ) { |
|
1636 $url = add_query_arg( |
|
1637 array( |
|
1638 'tab' => 'plugin-information', |
|
1639 'plugin' => $slug, |
|
1640 'TB_iframe' => 'true', |
|
1641 'width' => '600', |
|
1642 'height' => '550', |
|
1643 ), |
|
1644 network_admin_url( 'plugin-install.php' ) |
|
1645 ); |
|
1646 |
|
1647 $name_attr = esc_attr( $name ); |
|
1648 return sprintf( |
|
1649 "<a href='%s' class='thickbox open-plugin-details-modal' aria-label='%s' data-title='%s'>%s</a>", |
|
1650 esc_url( $url ), |
|
1651 /* translators: %s: Plugin name. */ |
|
1652 sprintf( __( 'More information about %s' ), $name_attr ), |
|
1653 $name_attr, |
|
1654 esc_html( $name ) |
|
1655 ); |
|
1656 } |
1372 } |
1657 } |