Tamam, bunu bir bıçaklayacağım. Yol boyunca karşılaştığım bazı sınırlamalar:
WP_List_Table alt sınıflarında çok fazla filtre yok, en azından hiç olmaları gereken yerde değil.
Bu filtre eksikliği nedeniyle, en üstte doğru bir eklenti türü listesi tutamıyoruz.
Ayrıca eklentileri aktif olarak görüntülemek için bazı harika (okuma: kirli) JavaScript kodları kullanmamız gerekiyor.
Yönetici alan kodumu bir sınıfın içine sardım, bu yüzden işlev isimlerim ön ekli değil. Bu kodun tamamını burada görebilirsiniz . Lütfen katkıda bulunun!
Merkez API
Eklenti dizinlerimizi ilişkisel bir dizide içerecek global bir değişken oluşturan basit bir işlev. $key
Vb eklentileri almak için dahili olarak kullanılan bir şey olacak $dir
ya tam bir yol ya da bir şey görecelidir wp-content
dizine. $label
admin alanındaki gösterimiz için olacak (örneğin çevrilebilir bir dize).
<?php
function register_plugin_directory( $key, $dir, $label )
{
global $wp_plugin_directories;
if( empty( $wp_plugin_directories ) ) $wp_plugin_directories = array();
if( ! file_exists( $dir ) && file_exists( trailingslashit( WP_CONTENT_DIR ) . $dir ) )
{
$dir = trailingslashit( WP_CONTENT_DIR ) . $dir;
}
$wp_plugin_directories[$key] = array(
'label' => $label,
'dir' => $dir
);
}
O zaman elbette eklentileri yüklemeliyiz. İçine Hook plugins_loaded
şekilde geç ve her yükleme, aktif eklentileri geçmesi.
Yönetici Alanı
İşlevselliğimizi bir sınıf içinde kuralım.
<?php
class CD_APD_Admin
{
/**
* The container for all of our custom plugins
*/
protected $plugins = array();
/**
* What custom actions are we allowed to handle here?
*/
protected $actions = array();
/**
* The original count of the plugins
*/
protected $all_count = 0;
/**
* constructor
*
* @since 0.1
*/
function __construct()
{
add_action( 'load-plugins.php', array( &$this, 'init' ) );
add_action( 'plugins_loaded', array( &$this, 'setup_actions' ), 1 );
}
} // end class
Biz içine kanca gidiyoruz plugins_loaded
gerçekten erken ve kullanacağımız izin "eylemleri" kurdu. Bunlar, yerleşik işlevler özel dizinlerle yapamadığından eklenti etkinleştirme ve devre dışı bırakma işlemlerini gerçekleştirir.
function setup_actions()
{
$tmp = array(
'custom_activate',
'custom_deactivate'
);
$this->actions = apply_filters( 'custom_plugin_actions', $tmp );
}
Sonra bağlı fonksiyonu var load-plugins.php
. Bu her türlü eğlenceli şeyi yapar.
function init()
{
global $wp_plugin_directories;
$screen = get_current_screen();
$this->get_plugins();
$this->handle_actions();
add_filter( 'views_' . $screen->id, array( &$this, 'views' ) );
// check to see if we're using one of our custom directories
if( $this->get_plugin_status() )
{
add_filter( 'views_' . $screen->id, array( &$this, 'views_again' ) );
add_filter( 'all_plugins', array( &$this, 'filter_plugins' ) );
// TODO: support bulk actions
add_filter( 'bulk_actions-' . $screen->id, '__return_empty_array' );
add_filter( 'plugin_action_links', array( &$this, 'action_links' ), 10, 2 );
add_action( 'admin_enqueue_scripts', array( &$this, 'scripts' ) );
}
}
Her seferinde bir şeyi geçelim. get_plugins
yöntem olup, bir fonksiyon etrafında bir sarıcı. Özniteliği plugins
veriyle doldurur .
function get_plugins()
{
global $wp_plugin_directories;
foreach( array_keys( $wp_plugin_directories ) as $key )
{
$this->plugins[$key] = cd_apd_get_plugins( $key );
}
}
cd_apd_get_plugins
get_plugins
kodlanmış WP_CONTENT_DIR
ve işsiz yerleşik fonksiyonun bir yırtıktır plugins
. Temel olarak: dizini $wp_plugin_directories
globalden alın, açın, tüm eklenti dosyalarını bulun. Daha sonra bunları önbellekte saklayın.
<?php
function cd_apd_get_plugins( $dir_key )
{
global $wp_plugin_directories;
// invalid dir key? bail
if( ! isset( $wp_plugin_directories[$dir_key] ) )
{
return array();
}
else
{
$plugin_root = $wp_plugin_directories[$dir_key]['dir'];
}
if ( ! $cache_plugins = wp_cache_get( 'plugins', 'plugins') )
$cache_plugins = array();
if ( isset( $cache_plugins[$dir_key] ) )
return $cache_plugins[$dir_key];
$wp_plugins = array();
$plugins_dir = @ opendir( $plugin_root );
$plugin_files = array();
if ( $plugins_dir ) {
while ( ( $file = readdir( $plugins_dir ) ) !== false ) {
if ( substr($file, 0, 1) == '.' )
continue;
if ( is_dir( $plugin_root.'/'.$file ) ) {
$plugins_subdir = @ opendir( $plugin_root.'/'.$file );
if ( $plugins_subdir ) {
while (($subfile = readdir( $plugins_subdir ) ) !== false ) {
if ( substr($subfile, 0, 1) == '.' )
continue;
if ( substr($subfile, -4) == '.php' )
$plugin_files[] = "$file/$subfile";
}
closedir( $plugins_subdir );
}
} else {
if ( substr($file, -4) == '.php' )
$plugin_files[] = $file;
}
}
closedir( $plugins_dir );
}
if ( empty($plugin_files) )
return $wp_plugins;
foreach ( $plugin_files as $plugin_file ) {
if ( !is_readable( "$plugin_root/$plugin_file" ) )
continue;
$plugin_data = get_plugin_data( "$plugin_root/$plugin_file", false, false ); //Do not apply markup/translate as it'll be cached.
if ( empty ( $plugin_data['Name'] ) )
continue;
$wp_plugins[trim( $plugin_file )] = $plugin_data;
}
uasort( $wp_plugins, '_sort_uname_callback' );
$cache_plugins[$dir_key] = $wp_plugins;
wp_cache_set('plugins', $cache_plugins, 'plugins');
return $wp_plugins;
}
Bir sonraki adım, eklentileri gerçekten etkinleştirip devre dışı bırakmanın sinir bozucu işi. Bunu yapmak için handle_actions
yöntemi kullanıyoruz. Bu, yine, çekirdek wp-admin/plugins.php
dosyanın üstünden açıkça sökülüp atılmıştır .
function handle_actions()
{
$action = isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : '';
// not allowed to handle this action? bail.
if( ! in_array( $action, $this->actions ) ) return;
// Get the plugin we're going to activate
$plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : false;
if( ! $plugin ) return;
$context = $this->get_plugin_status();
switch( $action )
{
case 'custom_activate':
if( ! current_user_can('activate_plugins') )
wp_die( __('You do not have sufficient permissions to manage plugins for this site.') );
check_admin_referer( 'custom_activate-' . $plugin );
$result = cd_apd_activate_plugin( $plugin, $context );
if ( is_wp_error( $result ) )
{
if ( 'unexpected_output' == $result->get_error_code() )
{
$redirect = add_query_arg( 'plugin_status', $context, self_admin_url( 'plugins.php' ) );
wp_redirect( add_query_arg( '_error_nonce', wp_create_nonce( 'plugin-activation-error_' . $plugin ), $redirect ) ) ;
exit();
}
else
{
wp_die( $result );
}
}
wp_redirect( add_query_arg( array( 'plugin_status' => $context, 'activate' => 'true' ), self_admin_url( 'plugins.php' ) ) );
exit();
break;
case 'custom_deactivate':
if ( ! current_user_can( 'activate_plugins' ) )
wp_die( __('You do not have sufficient permissions to deactivate plugins for this site.') );
check_admin_referer('custom_deactivate-' . $plugin);
cd_apd_deactivate_plugins( $plugin, $context );
if ( headers_sent() )
echo "<meta http-equiv='refresh' content='" . esc_attr( "0;url=plugins.php?deactivate=true&plugin_status=$status&paged=$page&s=$s" ) . "' />";
else
wp_redirect( self_admin_url("plugins.php?deactivate=true&plugin_status=$context") );
exit();
break;
default:
do_action( 'custom_plugin_dir_' . $action );
break;
}
}
Birkaç özel burada tekrar çalışır. cd_apd_activate_plugin
(koparıldı activate_plugin
) ve cd_apd_deactivate_plugins
(koparıldı deactivate_plugins
). Her ikisi de, kodlanmış dizinleri olmayan ilgili "ebeveyn" işlevleriyle aynıdır.
function cd_apd_activate_plugin( $plugin, $context, $silent = false )
{
$plugin = trim( $plugin );
$redirect = add_query_arg( 'plugin_status', $context, admin_url( 'plugins.php' ) );
$redirect = apply_filters( 'custom_plugin_redirect', $redirect );
$current = get_option( 'active_plugins_' . $context, array() );
$valid = cd_apd_validate_plugin( $plugin, $context );
if ( is_wp_error( $valid ) )
return $valid;
if ( !in_array($plugin, $current) ) {
if ( !empty($redirect) )
wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), $redirect)); // we'll override this later if the plugin can be included without fatal error
ob_start();
include_once( $valid );
if ( ! $silent ) {
do_action( 'custom_activate_plugin', $plugin, $context );
do_action( 'custom_activate_' . $plugin, $context );
}
$current[] = $plugin;
sort( $current );
update_option( 'active_plugins_' . $context, $current );
if ( ! $silent ) {
do_action( 'custom_activated_plugin', $plugin, $context );
}
if ( ob_get_length() > 0 ) {
$output = ob_get_clean();
return new WP_Error('unexpected_output', __('The plugin generated unexpected output.'), $output);
}
ob_end_clean();
}
return true;
}
Ve deaktivasyon işlevi
function cd_apd_deactivate_plugins( $plugins, $context, $silent = false ) {
$current = get_option( 'active_plugins_' . $context, array() );
foreach ( (array) $plugins as $plugin )
{
$plugin = trim( $plugin );
if ( ! in_array( $plugin, $current ) ) continue;
if ( ! $silent )
do_action( 'custom_deactivate_plugin', $plugin, $context );
$key = array_search( $plugin, $current );
if ( false !== $key ) {
array_splice( $current, $key, 1 );
}
if ( ! $silent ) {
do_action( 'custom_deactivate_' . $plugin, $context );
do_action( 'custom_deactivated_plugin', $plugin, $context );
}
}
update_option( 'active_plugins_' . $context, $current );
}
cd_apd_validate_plugin
Elbette, validate_plugin
zor kodlanmış hurdaların olmadığı bir paramparça olan fonksiyon da var .
<?php
function cd_apd_validate_plugin( $plugin, $context )
{
$rv = true;
if ( validate_file( $plugin ) )
{
$rv = new WP_Error('plugin_invalid', __('Invalid plugin path.'));
}
global $wp_plugin_directories;
if( ! isset( $wp_plugin_directories[$context] ) )
{
$rv = new WP_Error( 'invalid_context', __( 'The context for this plugin does not exist' ) );
}
$dir = $wp_plugin_directories[$context]['dir'];
if( ! file_exists( $dir . '/' . $plugin) )
{
$rv = new WP_Error( 'plugin_not_found', __( 'Plugin file does not exist.' ) );
}
$installed_plugins = cd_apd_get_plugins( $context );
if ( ! isset($installed_plugins[$plugin]) )
{
$rv = new WP_Error( 'no_plugin_header', __('The plugin does not have a valid header.') );
}
$rv = $dir . '/' . $plugin;
return $rv;
}
Tamam, bunun dışında. Liste tablosunun görüntüsü hakkında konuşmaya başlayabiliriz.
1. Adım: görünümlerimizi tablonun en üstündeki listeye ekleyin. Bu, fonksiyonumuza filtre views_{$screen->id}
uygulayarak yapılır init
.
add_filter( 'views_' . $screen->id, array( &$this, 'views' ) );
Daha sonra gerçek çengel işlevi sadece içinden geçiyor $wp_plugin_directories
. Yeni kayıtlı dizinlerden birinin eklentileri varsa, ekrana ekleriz.
function views( $views )
{
global $wp_plugin_directories;
// bail if we don't have any extra dirs
if( empty( $wp_plugin_directories ) ) return $views;
// Add our directories to the action links
foreach( $wp_plugin_directories as $key => $info )
{
if( ! count( $this->plugins[$key] ) ) continue;
$class = $this->get_plugin_status() == $key ? ' class="current" ' : '';
$views[$key] = sprintf(
'<a href="%s"' . $class . '>%s <span class="count">(%d)</span></a>',
add_query_arg( 'plugin_status', $key, 'plugins.php' ),
esc_html( $info['label'] ),
count( $this->plugins[$key] )
);
}
return $views;
}
Özel bir eklenti dizini sayfasını görüntülüyor olmamız durumunda yapmanız gereken ilk şey, görünümleri yeniden filtrelemek. Sayıdan kurtulmamız gerekiyor, inactive
çünkü doğru olmayacak. Bunun bir sonucu olarak, ihtiyaç duyduğumuz yerde hiçbir filtre olmamıştır. Tekrar bağla ...
if( $this->get_plugin_status() )
{
add_filter( 'views_' . $screen->id, array( &$this, 'views_again' ) );
}
Ve hızlı bir üzücü ...
function views_again( $views )
{
if( isset( $views['inactive'] ) ) unset( $views['inactive'] );
return $views;
}
Daha sonra, liste tablosunda göreceğiniz eklentilerden kurtulalım ve bunları özel eklentilerimizle değiştirelim. İçine kanca all_plugins
.
if( $this->get_plugin_status() )
{
add_filter( 'views_' . $screen->id, array( &$this, 'views_again' ) );
add_filter( 'all_plugins', array( &$this, 'filter_plugins' ) );
}
Eklentilerimizi ve verilerimizi zaten kurduğumuzdan (yukarıya bakın setup_plugins
), filter_plugins
sadece (1) yöntemi tüm eklentilerdeki sayımı daha sonra kaydeder ve (2) liste tablosundaki eklentileri değiştirir.
function filter_plugins( $plugins )
{
if( $key = $this->get_plugin_status() )
{
$this->all_count = count( $plugins );
$plugins = $this->plugins[$key];
}
return $plugins;
}
Ve şimdi toplu eylemleri öldüreceğiz. Bunlar kolayca desteklenebilir, sanırım?
if( $this->get_plugin_status() )
{
add_filter( 'views_' . $screen->id, array( &$this, 'views_again' ) );
add_filter( 'all_plugins', array( &$this, 'filter_plugins' ) );
// TODO: support bulk actions
add_filter( 'bulk_actions-' . $screen->id, '__return_empty_array' );
}
Varsayılan eklenti işlemleri bağlantıları bizim için çalışmayacak. Bunun yerine, kendimizi (özel eylemlerle vb.) Kurmamız gerekiyor. In init
fonksiyonu.
if( $this->get_plugin_status() )
{
add_filter( 'views_' . $screen->id, array( &$this, 'views_again' ) );
add_filter( 'all_plugins', array( &$this, 'filter_plugins' ) );
// TODO: support bulk actions
add_filter( 'bulk_actions-' . $screen->id, '__return_empty_array' );
add_filter( 'plugin_action_links', array( &$this, 'action_links' ), 10, 2 );
}
Burada değiştirilen tek şey (1) eylemleri değiştiriyoruz, (2) eklenti durumunu koruyor ve (3) olmayan isimleri biraz değiştiriyoruz.
function action_links( $links, $plugin_file )
{
$context = $this->get_plugin_status();
// let's just start over
$links = array();
$links['activate'] = sprintf(
'<a href="%s" title="Activate this plugin">%s</a>',
wp_nonce_url( 'plugins.php?action=custom_activate&plugin=' . $plugin_file . '&plugin_status=' . esc_attr( $context ), 'custom_activate-' . $plugin_file ),
__( 'Activate' )
);
$active = get_option( 'active_plugins_' . $context, array() );
if( in_array( $plugin_file, $active ) )
{
$links['deactivate'] = sprintf(
'<a href="%s" title="Deactivate this plugin" class="cd-apd-deactivate">%s</a>',
wp_nonce_url( 'plugins.php?action=custom_deactivate&plugin=' . $plugin_file . '&plugin_status=' . esc_attr( $context ), 'custom_deactivate-' . $plugin_file ),
__( 'Deactivate' )
);
}
return $links;
}
Ve son olarak, üstesinden gelmek için biraz JavaScript kullanmamız gerekiyor. In init
fonksiyonu tekrar (hep birlikte bu kez).
if( $this->get_plugin_status() )
{
add_filter( 'views_' . $screen->id, array( &$this, 'views_again' ) );
add_filter( 'all_plugins', array( &$this, 'filter_plugins' ) );
// TODO: support bulk actions
add_filter( 'bulk_actions-' . $screen->id, '__return_empty_array' );
add_filter( 'plugin_action_links', array( &$this, 'action_links' ), 10, 2 );
add_action( 'admin_enqueue_scripts', array( &$this, 'scripts' ) );
}
JS'imizi zorlarken wp_localize_script
toplam "tüm eklentiler" sayısının değerini almak için de kullanırız .
function scripts()
{
wp_enqueue_script(
'cd-apd-js',
CD_APD_URL . 'js/apd.js',
array( 'jquery' ),
null
);
wp_localize_script(
'cd-apd-js',
'cd_apd',
array(
'count' => esc_js( $this->all_count )
)
);
}
Ve elbette, JS liste tablosunu etkin / etkin olmayan eklentilerin düzgün şekilde görüntülemesini sağlamak için sadece bazı hoş hack'lerdir. Ayrıca tüm eklentilerin doğru sayısını tekrar All
bağlantıya yapıştırırız .
jQuery(document).ready(function(){
jQuery('li.all a').removeClass('current').find('span.count').html('(' + cd_apd.count + ')');
jQuery('.wp-list-table.plugins tr').each(function(){
var is_active = jQuery(this).find('a.cd-apd-deactivate');
if(is_active.length) {
jQuery(this).removeClass('inactive').addClass('active');
jQuery(this).find('div.plugin-version-author-uri').removeClass('inactive').addClass('active');
}
});
});
Sarmak
Eklenti dizinlerinin gerçek yüklenmesi oldukça heyecan vericidir. Liste tablosunun doğru görüntülenmesini sağlamak daha zor olan kısımdır. Yine de sonuçlarından tamamen memnun değilim, ancak belki birileri kodu iyileştirebilir