Kaldır, Etkinleştir, Bir eklentiyi devre dışı bırak: tipik özellikler ve nasıl yapılır


100

WordPress eklentisi yapıyorum. Kaldırma özelliğine dahil etmem gereken tipik şeyler nelerdir?

Örneğin, kurulum fonksiyonunda yarattığım tabloları silmeli miyim?

Seçenek girişlerimi temizler miyim?

Başka herhangi bir şey?


Çalışması için çok zaman harcadım. Sorun, giriş kancasının kayıt kancalarının içinde çalışmamasıdır. Sanırım bir kanca (eylem veya filtre) bu kadar erken çalışmayacak. Aşağıdaki bağlantıyı notları okuyun. codex.wordpress.org/Function_Reference/register_activation_hook Diyor ki: "Kancayı plugins_loaded kancaya kaydetmek çok geç ve çalışmaz! (register_deactivation_hook kancaya kadar çalışsa bile)"
Anton

Kodeksi sizin bahsettiğiniz şeyle güncelleyen kişi benim, bu yüzden yukarıdaki cevabında göz önüne alınıyor. :)
kaiser

Yanıtlar:


150

Üç farklı kanca var. Aşağıdaki durumlarda tetiklerler:

  • Kaldırma
  • etkisizleştirme
  • etkinleştirme

Senaryolar sırasında güvenli bir şekilde nasıl tetiklenir

Aşağıda, söz konusu eylemler sırasında tetiklenen geri çağırma işlevlerini güvenli şekilde bağlamanın doğru yolları gösterilmektedir .

Bu kodu kullanan bir eklentide kullanabildiğiniz gibi

  • düz fonksiyonlar
  • bir sınıf veya
  • harici bir sınıf,

İnceleyebileceğiniz üç farklı demo eklentisi göstereceğim ve daha sonra kodu kendi eklentilerinize uygulayacağım.

Önemli not önceden!

Bu konu son derece zor ve çok ayrıntılı olduğu ve bir düzine + son durumu olduğu için bu cevap asla mükemmel olmayacak. Zamanla geliştirmeye devam edeceğim, bu yüzden düzenli olarak tekrar kontrol edin.

(1) Eklentileri etkinleştirin / devre dışı bırakın / kaldırın.

Eklenti ayarları geri aramaları çekirdek tarafından tetiklenir ve bunun çekirdeğin bunu yapması üzerinde hiçbir etkisi olmaz. Akılda tutulması gereken bazı şeyler var:

  • echo/printKurulum geri aramaları sırasında asla , hiçbir şey (!). Bu headers already sentmesaj yol açacaktır ve çekirdek eklentinizi devre dışı bırakmanızı ve silmenizi önerecektir ... sorma: Bilmiyorum ...
  • Sen olmayacak bkz herhangi bir görsel çıktı. Ancakexit() farklı geri aramalara ifadeler ekledim, böylece gerçekte neler olduğu hakkında bazı bilgiler edinebilirsiniz. İşleri görmek için onları rahatsız et.
  • __FILE__ != WP_PLUGIN_INSTALLBirinin eklentiyi gerçekten kaldırıp kaldırmadığını görmek için kontrol edip etmemeniz (eğer yoksa: iptal!). on_deactivation()Geliştirme sırasında yalnızca geri aramaları tetiklemenizi öneririm , bu yüzden her şeyi geri almanız gereken zamanı kendinize ayırın. En azından benim yaptığım şey bu.
  • Ben de bazı güvenlik işlerini yapıyorum. Bazıları çekirdek tarafından da yapılır, fakat hey! Pişman olmaktansa sağlamcı davranmak iyidir! .
    • İlk önce çekirdek yüklenmediğinde doğrudan dosya erişimine izin vermem: defined( 'ABSPATH' ) OR exit;
    • Sonra mevcut kullanıcının bu görevi yapmasına izin verilip verilmediğini kontrol ediyorum.
    • Son görev olarak yönlendirmeyi kontrol ediyorum. Not: Bir hata olduğunda ,wp_die() uygun izinler isteyen (ve tekrar denemek istersen ... evet, elbette ) bir ekranda beklenmeyen sonuçlar olabilir . Çekirdek, sizi yönlendirir akımını ayarlar olarak bu gerçekleşir $GLOBALS['wp_list_table']->current_action();için error_scrapeve daha sonra da yönlendirme denetler check_admin_referer('plugin-activation-error_' . $plugin);nerede $pluginolduğunu $_REQUEST['plugin']. Böylece yönlendirme sayfa yükünün yarısında gerçekleşir ve bu kablolu kaydırma çubuğunu alırsınız ve kalıp ekranı sarı yönetici bildirimi / mesaj kutusunu görür. Bu durumda: Sakin olun ve sadece bazı exit()ve adım adım hata ayıklama ile hatayı arayın .

(A) Düz fonksiyonlar eklentisi

İşlev tanımından önce geri aramaları bağlarsanız, bunun işe yaramayabileceğini unutmayın.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) Activate/Deactivate/Uninstall - Functions
 * Description: Example Plugin to show activation/deactivation/uninstall callbacks for plain functions.
 * Author:      Franz Josef Kaiser/wecodemore
 * Author URL:  http://unserkaiser.com
 * Plugin URL:  http://wordpress.stackexchange.com/questions/25910/uninstall-activate-deactivate-a-plugin-typical-features-how-to/25979#25979
 */

function WCM_Setup_Demo_on_activation()
{
    if ( ! current_user_can( 'activate_plugins' ) )
        return;
    $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
    check_admin_referer( "activate-plugin_{$plugin}" );

    # Uncomment the following line to see the function in action
    # exit( var_dump( $_GET ) );
}

function WCM_Setup_Demo_on_deactivation()
{
    if ( ! current_user_can( 'activate_plugins' ) )
        return;
    $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
    check_admin_referer( "deactivate-plugin_{$plugin}" );

    # Uncomment the following line to see the function in action
    # exit( var_dump( $_GET ) );
}

function WCM_Setup_Demo_on_uninstall()
{
    if ( ! current_user_can( 'activate_plugins' ) )
        return;
    check_admin_referer( 'bulk-plugins' );

    // Important: Check if the file is the one
    // that was registered during the uninstall hook.
    if ( __FILE__ != WP_UNINSTALL_PLUGIN )
        return;

    # Uncomment the following line to see the function in action
    # exit( var_dump( $_GET ) );
}

register_activation_hook(   __FILE__, 'WCM_Setup_Demo_on_activation' );
register_deactivation_hook( __FILE__, 'WCM_Setup_Demo_on_deactivation' );
register_uninstall_hook(    __FILE__, 'WCM_Setup_Demo_on_uninstall' );

(B) Bir sınıf tabanlı / OOP mimarisi

Bu, günümüzde eklentilerdeki en yaygın örnektir.

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) Activate/Deactivate/Uninstall - CLASS
 * Description: Example Plugin to show activation/deactivation/uninstall callbacks for classes/objects.
 * Author:      Franz Josef Kaiser/wecodemore
 * Author URL:  http://unserkaiser.com
 * Plugin URL:  http://wordpress.stackexchange.com/questions/25910/uninstall-activate-deactivate-a-plugin-typical-features-how-to/25979#25979
 */


register_activation_hook(   __FILE__, array( 'WCM_Setup_Demo_Class', 'on_activation' ) );
register_deactivation_hook( __FILE__, array( 'WCM_Setup_Demo_Class', 'on_deactivation' ) );
register_uninstall_hook(    __FILE__, array( 'WCM_Setup_Demo_Class', 'on_uninstall' ) );

add_action( 'plugins_loaded', array( 'WCM_Setup_Demo_Class', 'init' ) );
class WCM_Setup_Demo_Class
{
    protected static $instance;

    public static function init()
    {
        is_null( self::$instance ) AND self::$instance = new self;
        return self::$instance;
    }

    public static function on_activation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "activate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_deactivation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "deactivate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_uninstall()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        check_admin_referer( 'bulk-plugins' );

        // Important: Check if the file is the one
        // that was registered during the uninstall hook.
        if ( __FILE__ != WP_UNINSTALL_PLUGIN )
            return;

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public function __construct()
    {
        # INIT the plugin: Hook your callbacks
    }
}

(C) Harici bir kurulum nesnesine sahip bir sınıf tabanlı / OOP mimarisi

Bu senaryo, bir ana eklenti dosyası ve adında bir ikinci dosya var varsayar setup.phpadlı eklentinin bir alt dizinde inc: ~/wp-content/plugins/your_plugin/inc/setup.php. Bu, eklenti klasörü varsayılan WP klasörü yapısının dışındayken ve içerik dizinin yeniden adlandırıldığı veya kurulum dosyanızın farklı isimlendirildiği durumlarda olduğu gibi çalışacaktır. Yalnızca incklasör, eklentiler kök dizininden aynı ada ve yere sahip olmalıdır.

Not: Üç register_*_hook()*işlevi ve sınıfları alıp eklentinize bırakabilirsiniz.

Ana eklenti dosyası:

<?php
defined( 'ABSPATH' ) OR exit;
/**
 * Plugin Name: (WCM) Activate/Deactivate/Uninstall - FILE/CLASS
 * Description: Example Plugin
 * Author:      Franz Josef Kaiser/wecodemore
 * Author URL:  http://unserkaiser.com
 * Plugin URL:  http://wordpress.stackexchange.com/questions/25910/uninstall-activate-deactivate-a-plugin-typical-features-how-to/25979#25979
 */


register_activation_hook(   __FILE__, array( 'WCM_Setup_Demo_File_Inc', 'on_activation' ) );
register_deactivation_hook( __FILE__, array( 'WCM_Setup_Demo_File_Inc', 'on_deactivation' ) );
register_uninstall_hook(    __FILE__, array( 'WCM_Setup_Demo_File_Inc', 'on_uninstall' ) );

add_action( 'plugins_loaded', array( 'WCM_Setup_Demo_File', 'init' ) );
class WCM_Setup_Demo_File
{
    protected static $instance;

    public static function init()
    {
        is_null( self::$instance ) AND self::$instance = new self;
        return self::$instance;
    }

    public function __construct()
    {
        add_action( current_filter(), array( $this, 'load_files' ), 30 );
    }

    public function load_files()
    {
        foreach ( glob( plugin_dir_path( __FILE__ ).'inc/*.php' ) as $file )
            include_once $file;
    }
}

Kurulum dosyası:

<?php
defined( 'ABSPATH' ) OR exit;

class WCM_Setup_Demo_File_Inc
{
    public static function on_activation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "activate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_deactivation()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        $plugin = isset( $_REQUEST['plugin'] ) ? $_REQUEST['plugin'] : '';
        check_admin_referer( "deactivate-plugin_{$plugin}" );

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }

    public static function on_uninstall()
    {
        if ( ! current_user_can( 'activate_plugins' ) )
            return;
        check_admin_referer( 'bulk-plugins' );

        // Important: Check if the file is the one
        // that was registered during the uninstall hook.
        if ( __FILE__ != WP_UNINSTALL_PLUGIN )
            return;

        # Uncomment the following line to see the function in action
        # exit( var_dump( $_GET ) );
    }
}

(2) Eklenti güncellemeleri

Kendi DB tablosuna veya seçeneklerine sahip bir eklenti yazarsanız, şeyleri değiştirmeniz veya yükseltmeniz gereken senaryolar olabilir.

Ne yazık ki şu ana kadar eklenti / tema yükleme veya güncelleme / yükseltme üzerinde bir şey çalıştırma imkanı yoktur. İşe yarayacak bir şeyler var: Özel bir işlevi özel bir seçeneğe bağla (evet, bu topal - ama işe yarıyor).

function prefix_upgrade_plugin() 
{
    $v = 'plugin_db_version';
    $update_option = null;
    // Upgrade to version 2
    if ( 2 !== get_option( $v ) ) 
    {
        if ( 2 < get_option( $v ) )
        {
            // Callback function must return true on success
            $update_option = custom_upgrade_cb_fn_v3();

            // Only update option if it was an success
            if ( $update_option )
                update_option( $v, 2 );
        }
    }

    // Upgrade to version 3, runs just after upgrade to version 2
    if ( 3 !== get_option( $v ) ) 
    {
        // re-run from beginning if previous update failed
        if ( 2 < get_option( $v ) )
            return prefix_upgrade_plugin();

        if ( 3 < get_option( $v ) )
        {
            // Callback function must return true on success
            $update_option = custom_upgrade_cb_fn_v3();

            // Only update option if it was an success
            if ( $update_option )
                update_option( $v, 3 );
        }
    }

    // Return the result from the update cb fn, so we can test for success/fail/error
    if ( $update_option )
        return $update_option;

return false;
}
add_action('admin_init', 'prefix_upgrade_plugin' );

Kaynak

Bu güncelleme işlevi çok iyi olmayan / iyi yazılmış bir örnek, ancak dediği gibi: Bu bir örnek ve teknik iyi çalışıyor. Daha sonraki bir güncelleme ile bunu geliştirir.


1
Bu harika ama gerçekten bilmek istediğim, devre dışı bırakma yöntemime dahil etmem gereken şeyler. ?
kırmızı konservatuar

1
"BUT" reklamı: 3 yöntem olduğunu belirtmiştim. Biri etkinleştirme için, biri geçici olarak devre dışı bırakma, biri de untall. Imho "uninstall", "beni ve yaptığım her şeyi kaldır" der, "devre dışı bırak" geçici bir durumdur ve yeniden yapılabilir. Ancak: Güncellemeye bakınız. Q +'nız hakkında yorumlar ekledim, bazı geliştirme önerilerinde bulundum.
kaiser

3
Ah şimdi anlıyorum. Sadece bir soru, ne zaman kaldırılır çağrılır? Dosyalar silindiğinde ??
kırmızı konservatuar

1
@aendrew Onlar sadece tarafta kullanılır check_admin_referer(). Dezenfekte olmaları gerekmez çünkü çekirdek bunu kendisi yapmaz ve yine de onu sterilize edilmemiş $_REQUESTdeğerlerle karşılaştırabilir . Ama bunun için küçük kızlar gibi ağlamaya başlarlarsa, sadece kullanın filter_var()veya kullanın esc_attr().
kaiser

2
Wp_register_uninstall_hook kullanıyorsanız geri arama işlevinde WP_UNINSTALL_PLUGIN olup olmadığını kontrol etmemelisiniz, yalnızca uninstall.php
paul

17

Mevcut sistemi PHP versiyonu veya kurulu eklentiler gibi gerekli özellikler için test etmek için buna benzer bir şey kullanabilirsiniz:

<?php  # -*- coding: utf-8 -*-
/**
 * Plugin Name: T5 Check Plugin Requirements
 * Description: Test for PHP version and installed extensions
 * Plugin URI:
 * Version:     2013.03.31
 * Author:      Thomas Scholz
 * Author URI:  http://toscho.de
 * Licence:     MIT
 * License URI: http://opensource.org/licenses/MIT
 */

/*
 * Don't start on every page, the plugin page is enough.
 */
if ( ! empty ( $GLOBALS['pagenow'] ) && 'plugins.php' === $GLOBALS['pagenow'] )
    add_action( 'admin_notices', 't5_check_admin_notices', 0 );

/**
 * Test current system for the features the plugin needs.
 *
 * @return array Errors or empty array
 */
function t5_check_plugin_requirements()
{
    $php_min_version = '5.4';
    // see http://www.php.net/manual/en/extensions.alphabetical.php
    $extensions = array (
        'iconv',
        'mbstring',
        'id3'
    );
    $errors = array ();

    $php_current_version = phpversion();

    if ( version_compare( $php_min_version, $php_current_version, '>' ) )
        $errors[] = "Your server is running PHP version $php_current_version but
            this plugin requires at least PHP $php_min_version. Please run an upgrade.";

    foreach ( $extensions as $extension )
        if ( ! extension_loaded( $extension ) )
            $errors[] = "Please install the extension $extension to run this plugin.";

    return $errors;

}

/**
 * Call t5_check_plugin_requirements() and deactivate this plugin if there are error.
 *
 * @wp-hook admin_notices
 * @return  void
 */
function t5_check_admin_notices()
{
    $errors = t5_check_plugin_requirements();

    if ( empty ( $errors ) )
        return;

    // Suppress "Plugin activated" notice.
    unset( $_GET['activate'] );

    // this plugin's name
    $name = get_file_data( __FILE__, array ( 'Plugin Name' ), 'plugin' );

    printf(
        '<div class="error"><p>%1$s</p>
        <p><i>%2$s</i> has been deactivated.</p></div>',
        join( '</p><p>', $errors ),
        $name[0]
    );
    deactivate_plugins( plugin_basename( __FILE__ ) );
}

PHP 5.5 için bir kontrol ile test edin:

görüntü tanımını buraya girin


Karıştı, böylece temelde bir çağrı yoktur dokunun register_activation_hookneden kullanılmasın - burada? Ayrıca bu ateş öncesi veya sonrasında ortaya register_activation_hookçıkacak register_activation_hookve yukarıdakiler geçmezse bile ateşlenecek mi?
orionrush

Sadece eklenti sayfasındaki aktivasyon kancadan sonra çalışır.
fuxia

Anladım - ancak eklenti eklenti sayfasının dışında etkinleştirildiyse (tema bağımlılığının bir parçası olarak söyleyin), çekleriniz atlanmayacak mı? Bu yüzden hareketli çalıştı add_action( 'admin_notices', 't5_check_admin_notices', 0 );bir aktivasyon kanca içine ve eklenti kontrolleri yapmadan harekete geçirir. . .
orionrush

@kaiser aktivasyon kancasının nasıl çalıştığını açıkladı, bir alternatif göstermek istedim. Eklenti her sayfa için etkin değilse ölümcül bir hata olabilir, evet. Bu yaklaşım, ciddi bir yeniden yazma olmadan bir etkinleştirme kancası üzerinde çalışamaz, çünkü o kanca sonradan ateşlenir admin_notices.
fuxia

Aslında sadece kolay yolda tökezledi: stackoverflow.com/a/13927297/362445
orionrush
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.