আনইনস্টল করুন, সক্রিয় করুন, একটি প্লাগইন নিষ্ক্রিয় করুন: সাধারণ বৈশিষ্ট্য এবং কীভাবে how


100

আমি একটি ওয়ার্ডপ্রেস প্লাগইন তৈরি করছি। আনইনস্টল বৈশিষ্ট্যে আমার যে সাধারণ জিনিসগুলি অন্তর্ভুক্ত করা উচিত সেগুলি কি?

উদাহরণস্বরূপ, আমি ইনস্টল ফাংশনে আমার তৈরি করা কোনও টেবিলগুলি মুছতে হবে?

আমি কি আমার বিকল্প এন্ট্রিগুলি পরিষ্কার করব?

আর কিছু?


এটি কাজ করার জন্য আমি অনেক সময় নষ্ট করেছি। সমস্যাটি হ'ল এইড হুক নিবন্ধের হুকের ভিতরে কাজ করছে না। আমি অনুমান করি যে একটি হুক (ক্রিয়া বা ফিল্টার) এত তাড়াতাড়ি কাজ করবে না। নীচের লিঙ্কে নোট পড়ুন। কোডেক্স.ওয়ার্ডপ্রেস.আর. / ফাংশন_রিফারেন্স / রেজিস্টার_ অ্যাক্টিভেশন_হুক এটি বলেছে: "আপনার প্লাগইন-লোড হুকের ভিতরে হুক নিবন্ধন করা খুব দেরী এবং এটি চলবে না! (এমনকি wp_ লোড হুক অবধি রেজিস্ট্রার_অ্যাক্টিভেশন_হুকের জন্য কাজ করার সময় মনে হয় না।")
অ্যান্টন

আমিই সেই ব্যক্তি যিনি আপনার উল্লেখ অনুযায়ী কোডেক্সকে আপডেট করেছেন, সুতরাং এটি উপরের উত্তরটিতে বিবেচনা করা হবে। :)
কায়সার

উত্তর:


150

তিনটি পৃথক হুক আছে। তারা নিম্নলিখিত ক্ষেত্রে ট্রিগার:

  • আনইনস্টল
  • নিষ্ক্রিয়করণ
  • অ্যাক্টিভেশন

পরিস্থিতিগুলির সময় কীভাবে ট্রিগার করবেন তা নিরাপদে কাজ করে

নীচে উল্লিখিত ক্রিয়া চলাকালীন ট্রিগারযুক্ত কলব্যাক ফাংশন সুরক্ষিতভাবে হুক করার সঠিক উপায়গুলি দেখায় ।

যেহেতু আপনি এই কোডটি কোনও প্লাগইন ব্যবহার করতে পারেন যা ব্যবহার করে

  • সরল ফাংশন,
  • একটি বর্গ বা
  • একটি বাহ্যিক শ্রেণী,

আমি তিনটি ভিন্ন ডেমো প্লাগইন দেখাব যা আপনি পরিদর্শন করতে পারেন এবং তারপরে কোডটি নিজের প্লাগইন (গুলি) এ প্রয়োগ করতে পারেন।

সামনে গুরুত্বপূর্ণ নোট!

যেহেতু এই বিষয়টি অত্যন্ত কঠিন এবং অত্যন্ত বিশদজনক এবং এক ডজন + প্রান্তের মামলা রয়েছে, এই উত্তরটি কখনই নির্ভুল হতে পারে না। আমি সময়ের সাথে এটি উন্নতি করতে থাকব, তাই নিয়মিত বেসে ফিরে দেখুন।

(1) প্লাগইনগুলি সক্রিয় / নিষ্ক্রিয় / আনইনস্টল করুন।

প্লাগইন সেটআপ কলব্যাকগুলি কোর দ্বারা ট্রিগার করা হয় এবং কীভাবে কোর এটি করে আপনার কোনও প্রভাব নেই। কিছু বিষয় মনে রাখতে হবে:

  • কখনই না , echo/printসেটআপ কলব্যাকের সময় কখনও কোনও কিছু (!) নেই। এটি headers already sentবার্তার দিকে পরিচালিত করবে এবং কোর আপনার প্লাগইন নিষ্ক্রিয় করতে এবং মুছে ফেলার পরামর্শ দেবে ... জিজ্ঞাসা করবেন না: আমি জানি ...
  • আপনি কোনও ভিজ্যুয়াল আউটপুট দেখতে পাবেন না । তবে আমি exit()সমস্ত ভিন্ন কলব্যাকগুলিতে বিবৃতি যুক্ত করেছি যাতে আপনি কী ঘটছেন সে সম্পর্কে কিছুটা অন্তর্দৃষ্টি পেতে পারেন। স্টাফ কাজ করে দেখার জন্য কেবল তাদেরকে অসুবিধে করুন।
  • __FILE__ != WP_PLUGIN_INSTALLকেউ সত্যিই প্লাগইন আনইনস্টল করছে কিনা তা দেখার জন্য এবং (যদি না: বাতিল না করা!) পরীক্ষা করা অত্যন্ত গুরুত্বপূর্ণ তবে আপনি এটি পরীক্ষা করতে পারেন। আমি on_deactivation()উন্নয়নের সময় কেবল কলব্যাকগুলি ট্রিগার করার পরামর্শ দিই , তাই আপনি নিজেকে সেই সময়টি সাশ্রয় করুন যাতে আপনার সবকিছু ফিরিয়ে আনতে হবে At কমপক্ষে আমি যা করি এটি এটি।
  • আমি পাশাপাশি কিছু সুরক্ষা সামগ্রী করি। কিছু কোর পাশাপাশি করা হয়, কিন্তু আরে! দুঃখিত চেয়ে ভাল নিরাপদ!
    • কোরটি লোড না করা হলে প্রথমে আমি সরাসরি ফাইল অ্যাক্সেসটিকে অস্বীকার করি: defined( 'ABSPATH' ) OR exit;
    • তারপরে আমি পরীক্ষা করে দেখি যে বর্তমান ব্যবহারকারীকে এই কাজটি করার অনুমতি দেওয়া হয়েছে কিনা।
    • একটি শেষ কাজ হিসাবে, আমি রেফারার চেক। দ্রষ্টব্য: আপনি যখন কোনও ত্রুটি পেয়েছিলেন তখন wp_die()যথাযথ অনুমতি চাওয়ার জন্য স্ক্রিনের সাথে অপ্রত্যাশিত ফলাফল আসতে পারে (এবং আপনি যদি আবার চেষ্টা করতে চান ... তবে অবশ্যই )। এই ঘটনা যেমন কোর আপনি পুননির্দেশনা, বর্তমান সেট করে $GLOBALS['wp_list_table']->current_action();করতে error_scrapeএবং তারপর জন্য রেফারার পরীক্ষা check_admin_referer('plugin-activation-error_' . $plugin);, যেখানে $pluginহয় $_REQUEST['plugin']। পুনঃনির্দেশটি পৃষ্ঠার অর্ধেক লোডে ঘটে এবং আপনি এই তারযুক্ত স্ক্রোল বারটি পাবেন এবং ডাই স্ক্রিনের অন্তর্দৃষ্টি হলুদ অ্যাডমিন নোটিশ / বার্তা বাক্স পাবেন। যদি এটি ঘটে থাকে: শান্ত থাকুন এবং কিছু exit()এবং ধাপে ধাপে ডিবাগিংয়ের মাধ্যমে ত্রুটিটি অনুসন্ধান করুন ।

(ক) সরল ফাংশন প্লাগইন

মনে রাখবেন যে আপনি যদি ফাংশন সংজ্ঞার আগে কলব্যাকগুলি হুক করেন তবে এটি কাজ করবে না।

<?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' );

(খ) শ্রেণিভিত্তিক / ওওপি আর্কিটেকচার

এটি আজকাল প্লাগইনগুলির মধ্যে সবচেয়ে সাধারণ উদাহরণ।

<?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
    }
}

(গ) বাহ্যিক সেটআপ অবজেক্ট সহ একটি শ্রেণিভিত্তিক / ওওপি আর্কিটেকচার

এই দৃশ্যকল্প ধরে নেয় যে আপনি একটি প্রধান প্লাগ-ইন ফাইল এবং একটি দ্বিতীয় নামের ফাইল পেয়েছিলাম setup.phpনামে প্লাগইন একটি সাব ডিরেক্টরীতে inc: ~/wp-content/plugins/your_plugin/inc/setup.php। ডিফল্ট ডাব্লুপি ফোল্ডার কাঠামোর বাইরে প্লাগইন ফোল্ডারটি যখন কাজ করবে, তেমনি যখন কন্টেন্ট ডিয়ারের নাম পরিবর্তন করা হবে বা আপনার সেটআপ ফাইলটির আলাদা নামকরণ হয়েছে এমন ক্ষেত্রে এটি কাজ করবে। incপ্লাগইন রুট ডিরেক্টরি থেকে কেবল ফোল্ডারে একই নাম এবং অবস্থান সম্পর্কিত থাকতে হবে।

দ্রষ্টব্য: আপনি কেবল তিনটি register_*_hook()*ফাংশন এবং ক্লাস নিতে পারেন এবং এটিকে আপনার প্লাগইনে ফেলে দিতে পারেন।

প্রধান প্লাগইন ফাইল:

<?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;
    }
}

সেটআপ ফাইল:

<?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) প্লাগইন আপডেট

আপনি যদি এমন একটি প্লাগইন লিখেন যার নিজস্ব ডিবি টেবিল বা বিকল্প রয়েছে, এমন পরিস্থিতিতে থাকতে পারে যেখানে আপনাকে জিনিসগুলি পরিবর্তন করতে বা আপগ্রেড করতে হবে।

দুঃখজনকভাবে এখনও পর্যন্ত প্লাগইন / থিম ইনস্টল বা আপডেট / আপগ্রেডে কিছু চালানোর কোনও সম্ভাবনা নেই। আনন্দের সাথে একটি কাজ প্রায় আছে: একটি কাস্টম বিকল্পে একটি কাস্টম ফাংশন হুক (হ্যাঁ, এটি খোঁড়া - তবে এটি কার্যকর)।

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' );

উৎস

এই আপডেট ফাংশনটি খুব সুন্দর / ভাল-লিখিত উদাহরণ নয়, তবে যেমনটি বলেছেন: এটি একটি উদাহরণ এবং কৌশলটি ভালভাবে কাজ করে। পরবর্তী আপডেটের মাধ্যমে এটি উন্নত করবে।


1
এটি দুর্দান্ত তবে আমি যা জানতে চাই তা হ'ল এমন জিনিসগুলি যা আমার নিষ্ক্রিয় পদ্ধতিতে অন্তর্ভুক্ত করা উচিত ... উদাহরণস্বরূপ, আমি কি আমার টেবিলগুলি ডাটাবেসে মুছে ফেলতে পারি বা ব্যবহারকারীর মন পরিবর্তন করে এবং প্লাগইনটিকে পুনরায় সক্রিয় করার ক্ষেত্রে সেগুলি রেখে দেওয়া উচিত? ?
redconservatory

1
বিজ্ঞাপন "বুট": আমি উল্লেখ করেছি যে এখানে 3 টি পদ্ধতি রয়েছে। অ্যাক্টিভেশনের জন্য একটি, অস্থায়ী নিষ্ক্রিয়করণের জন্য একটি এবং একটি আনস্টল করার জন্য। ইমহো "আনইনস্টল" বলছেন "আমাকে এবং আমার সমস্ত কিছু সরান", যখন "নিষ্ক্রিয় করা" একটি অস্থায়ী অবস্থা এবং আবারও হয়ে যেতে পারে। তবে: আপডেট দেখুন। আমি আপনার কিউ + সম্পর্কে মন্তব্যগুলি কিছু বিকাশের প্রস্তাব দিয়ে বাড়িয়েছি।
কায়সার 21

3
আহ আমি এখন বুঝতে পারি। কেবল একটি প্রশ্ন, আনইনস্টল কখন ডাকা হবে? ফাইলগুলি মুছে ফেলা হবে ??
redconservatory

1
@Aendru- এ তারা কেবল পাশাপাশি ব্যবহৃত হয় check_admin_referer()। তাদের স্যানিটাইজ করার দরকার নেই কারণ কোর এটি নিজেই করে না এবং যাইহোক এটি অচিহ্নযুক্ত $_REQUESTমানগুলির সাথে তুলনা করবে । তবে যদি তারা এই কারণে ছোট মেয়েদের মতো কাঁদতে শুরু করে তবে কেবল ব্যবহার করুন filter_var()বা esc_attr()এটির উপরে।
কায়সার

2
Wp_register_uninstall_hook ব্যবহার করা হলে কলব্যাক ফাংশনে WP_UNINSTALL_PLUGIN- র পরীক্ষা করা উচিত নয়, কেবলমাত্র আপনি আনইনস্টল.এফপি ব্যবহার করেন
পল

17

পিএইচপি সংস্করণ বা ইনস্টল এক্সটেনশানগুলির মতো প্রয়োজনীয় বৈশিষ্ট্যগুলির জন্য বর্তমান সিস্টেমটি পরীক্ষা করতে আপনি এর মতো কিছু ব্যবহার করতে পারেন:

<?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__ ) );
}

পিএইচপি 5.5 এর জন্য একটি চেক সহ পরীক্ষা করুন:

এখানে চিত্র বর্ণনা লিখুন


বিভ্রান্তির ছোঁয়া, সুতরাং মূলত এখানে কোনও কল register_activation_hookনেই - কেন এটি ব্যবহার করবেন না? এছাড়াও এই আগুন কি আগে বা পরে আগুন জ্বালিয়ে register_activation_hookদেবে এবং register_activation_hookউপরেরটি পাস না হলেও?
orionrush

এটি কেবলমাত্র প্লাগইন পৃষ্ঠায় অ্যাক্টিভেশন হুকের পরে চলে।
ফুসিয়া

আমি দেখতে পাচ্ছি - তবে প্লাগইন যদি প্লাগইন পৃষ্ঠার বাইরে সক্রিয় করা হয় (থিম নির্ভরতার অংশ হিসাবে বলুন) তবে আপনার চেকগুলি এড়িয়ে যাবে? তাই আমি add_action( 'admin_notices', 't5_check_admin_notices', 0 );একটি অ্যাক্টিভেশন হুকের দিকে যাওয়ার চেষ্টা করেছি এবং চেকগুলি সম্পাদন না করেই প্লাগইনটি সক্রিয় হয়। । ।
orionrush

অ্যাক্টিভেশন হুক কীভাবে কাজ করে তা কাইজার ব্যাখ্যা করেছেন, আমি একটি বিকল্প দেখাতে চাইছিলাম। প্লাগইন প্রতি প্লাগইনটি সক্রিয় না করা হলে মারাত্মক ত্রুটি ঘটতে পারে, হ্যাঁ। এই পদ্ধতিটি গুরুতর পুনর্লিখন ছাড়া অ্যাক্টিভেশন হুকের উপর কাজ করতে পারে না, কারণ সেই হুকটি পরে প্রবাহিত হয় admin_notices
ফুসিয়া

আসলে শুধু সহজ পথে পদস্খলিত: stackoverflow.com/a/13927297/362445
orionrush
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.