WordPress Plugin Development
WordPress Plugin Development In Bangla Part-10: WordPress Custom Post, Post Metadata and Meta Box
WordPress Custom Post Types কি?
WordPress এ অনেক ধরণের কনটেন্ট রয়েছে , যেটাকে ওয়ার্ডপ্রেসের ভাষায় বলা হয় Post Type. ওয়ার্ডপ্রেসের প্রত্যেকটি single item কে বলা হয় Post . বাই ডিফল্ট ওয়ার্ডপ্রেসে ৫ ধরণের post রয়েছে , যা ওয়ার্ডপ্রেস ডাটাবেসের wp_posts table এ সংরক্ষিত থাকে। আর এই WordPress Post Type গুলো হচ্ছে :
- Posts
- Pages
- Attachments
- Revisions
- Navigation Menus
আর যখন আমরা কোনো নতুন প্লাগিন ডেভেলপ করতে যাবো, তখন আমাদেরকে নিজেদের specific content type তৈরি করতে হবে। যেমন : e-commerce এর জন্য product সমূহ , e-learning website এর জন্য assignment সমূহ অথবা review website এর জন্য movies. আর এইরকম নিজেদের ইচ্ছামতো post types তৈরিকে বলা হয় Custom Post Types . এখন আমরা ওয়ার্ডপ্রেসের Custom Post Types নিয়ে আলোচনা করব। তো চলুন শুরু করা যাক :
কিভাবে ওয়ার্ডপ্রেসে Custom Post Types তৈরি করা হয়।?
ওয়ার্ডপ্রেসে Custom Post Types তৈরি করতে হলে , প্রথমে আমাদেরকে আমাদের custom post type কে register_post_type() function ব্যবহার করে ওয়ার্ডপ্রেসে রেজিস্ট্রেশন করে নিতে হবে। আর যখন রেজিস্ট্রেশন হয়ে যাবে , তখন আমাদের জন্য এটি WordPress এর top-level administrative screen এ চলে আসবে। এবং আমরা সেটিকে আমাদের custom posts এর manage এবং create এর কাজে ব্যবহার করতে পারব। চলুন দেখা যাক কিভাবে register_post_type() function কে ব্যবহার করে একটা custom post type কে রেজিস্টার করা যায়।
register_post_type() Function Syntax
register_post_type( string $post_type, array|string $args = array() );
Parameters #
- $post_type (string) (Required) এখানে আপনার custom Post type এর key টা দিবেন। তবে খেয়াল রাখতে হবে key টা যেন কোনো ভাবেই 20 characters এর বেশি না হয়। এবং অবশ্যই lowercase alphanumeric characters, dashes, এবং underscores দিয়ে হতে হবে। দেখুন sanitize_key().
- $args (array|string) (Optional) post type কে register করার জন্য আর্গুমেন্টস গুলোকে Array অথবা string আকারে চাইলে দিতে পারেন। নিচে প্রত্যেকটি argument সম্পর্কে বিস্তারিত বর্ণনা করা হলো।
- ‘label’ (string) চাইলে আপনার post type এর একটা নাম দিতে পারেন। সাধারণত নামটি plural হয়। আর Default value হচ্ছে $labels[‘name’].
- ‘labels’ (array) আপনার post type এর labels গুলোকে array আকারে এখানে দিতে হবে। যেমন : ‘name’, ‘singular_name’, ‘add_new_item’, ‘all_items’, ‘edit_item’, ‘new_item’, ‘view_item’, ‘not_found’, ‘not_found_in_trash’ ইত্যাদি।
- ‘description’ (string) আপনার post type এর একটা short description চাইলে এখানে দিতে পারেন।
- ‘public’ (bool) আপনার post type টি কিসে ব্যবহারের জন্য তৈরি , অর্থাৎ publicly admin interface এর জন্য? নাকি front-end users দের জন্যে। যদিও default settings গুলো যেমন $exclude_from_search, publicly_queryable, $show_ui, এবং $show_in_nav_menus গুলো public থেকেই inherited হয়। , এগুলোর প্রত্যেকেই কোনো relationship এর উপর নির্ভর করে না। Default false.
- ‘hierarchical’ (bool) post type টি hierarchical (e.g. page) হবে কিনা , চাইলে তা বলে দিতে পারেন। Default false.
- ‘exclude_from_search’ (bool) front end search results থেকে বাদ দিতে চাইলে এটি দিতে পারেন। এটার Default সবসময় আপনার $public argument এর বিপরীত টা হয়।
- ‘publicly_queryable’ (bool) যখন query গুলো post type এর জন্য front end এর জন্য parse_request() এর পার্ট হিসেবে কাজ করে। সাধারণত Endpoints গুলো হচ্ছে : * ?post_type={post_type_key}, * ?{post_type_key}={single_post_slug}, * ?{post_type_query_var}={single_post_slug} আর যদি set করা না হয়ে থাকে , তাহলে বাই ডিফল্ট $public থেকে inherited হয়।
- ‘show_ui’ (bool) এই post type managing এর জন্য যদি কোনো admin ui allow করতে চান তাহলে এখানে true দিতে হবে। By Default: $public.
- ‘show_in_menu’ (bool|string) :Where to show the post type in the admin menu এর যেই পজিশনে এই post type টি show করতে চান, সেটি এখানে বলতে হবে। তবে তার জন্যে আপনাকে $show_ui এর value কে অবশ্যই true করে দিতে হবে। আর যখন true করে দিবেন , তখন post type admin screen এ একটা top level menu হিসেবে আসবে। আর যদি false হয় , তাহলে কোনো menu show করবেনা। আর যদি বিদ্যমান কোনো top level menu এর string দেওয়া হয় (যেমন : ‘tools.php’ or ‘edit.php?post_type=page’), তখন নতুন post type এগুলোর sub menu হিসেবে আসবে। . Default:$show_ui.
- ‘show_in_nav_menus’ (bool) যদি এই post type কে navigation menus এর অধীনে দেখাতে চান , তাহলে এখানে true দিতে হবে। তবে by Default এখানে $public এর value থাকে।
- ‘show_in_admin_bar’ (bool) যদি এই post type কে admin bar এর অধীনে দেখাতে চান , তাহলে এখানে true দিতে হবে। তবে by Default এখানে $show_in_menu থাকে।
- ‘show_in_rest’ (bool) যদি post type কে REST API তে অন্তর্ভুক্ত করতে চান , তাহলে এখানে true দিতে হবে। এছাড়া যদি post type এ block editor রাখতে চান, তাহলেও এখানে true দিতে হবে।
- ‘rest_base’ (string) REST API route এর base url চাইলে দিতে পারেন। Default: $post_type.
- ‘rest_controller_class’ (string) REST API Controller class এর নাম এখানে হবে। আর Default হচ্ছে ‘WP_REST_Posts_Controller’.
- ‘menu_position’ (int) Tmenu Order এর পজিশন এখানে বলে দিতে পারেন। আর এটা কার্যকর করতে হলে অবশ্যই $show_in_menu এর value true হতে থাকতে হবে।
- ‘menu_icon’ (string) Menu টির যদি কোনো icon ব্যবহার করতে চান তার URL এখানে দিতে হবে। এখানে যদি data URI ব্যবহার করে কোনো base64-encoded SVG Image ব্যবহার করেন , তাহলে অবশ্যই data URI টি ‘data:image/svg+xml;base64,’ দিয়ে শুরু করা উচিত। আর যদি font icon ব্যবহার করতে চান তাহলে Dashicons helper class ব্যবহার করতে পারেন। যেমন : dashicons-chart-pie . আর যদি div.wp-menu-image এটি বাদ দিতে চান , এবং নিজস্ব CSS ব্যবহার করতে চান , তাহলে none পাস করতে হবে।
- ‘capability_type’ (string) এখানে একটা capability type string দিবেন , যাকে read, edit, and delete capabilities দিবেন। তবে চাইলে একাধিক string কে array আকারে পাঠাতে পারেন যেমন : array(‘story’, ‘stories’). আর বাই ডিফল্ট হচ্ছে ‘post’.
- ‘capabilities’ (array) এখানে এই post type এর যেই যেই capability দিবেন , সেটাকে একটা Array oআকারে দিবেন। $capability_type ভ্যারিয়েবল capabilities গুলোর জন্য একটা base হিসেবে ব্যবহৃত হয়। একটা post type এ কি কি capability থাকে তা জানতে চাইলে get_post_type_capabilities() ফাঙ্কশন টি ব্যবহার করতে পারেন।
- ‘map_meta_cap’ (bool) internal default meta capability handling ব্যবহার হবে কি না ? তা এখানে দিতে পারেন। Default false.
- ‘supports’ (array) Core feature(s) এর কি কি post type support করবে তা এখানে বলতে পারেন। এটা add_post_type_support() ফাঙ্কশনের alias হিসেবে ব্যবহৃত হয়। . Core features গুলোর মধ্যে থাকে ‘title’, ‘editor’, ‘comments’, ‘revisions’, ‘trackbacks’, ‘author’, ‘excerpt’, ‘page-attributes’, ‘thumbnail’, ‘custom-fields’, and ‘post-formats’ ইত্যাদি।
- ‘register_meta_box_cb’ (callable) এটা একটা একটা callback function দেয় ,যা meta boxes গুলো সেট করে।আসলে আপনার জন্য remove_meta_box() এবং add_meta_box() ফাঙ্কশনের কাজ করবে . Default null.
- ‘taxonomies’ (array) এখানে taxonomy identifiers গুলোকে একটা array আকারে দিতে হবে। যা post type এর জন্য registered হবে। তবে আপনি চাইলে Taxonomies গুলোকে register_taxonomy() অথবা register_taxonomy_for_object_type() দিয়ে পরেও registered করতে পারবেন।
- ‘has_archive’ (bool|string) post type টি archive হবে কিনা সেটা এখানে বলতে পারেন। Default false.
- ‘rewrite’ (bool|array) এই post type এর rewrite কে চাইলে এখানে বন্ধ করে দিতে পারেন। আর বন্ধ করতে চাইলে এখানে false দিতে পারেন। তবে ডিফল্ট হচ্ছে true. তবে $post_type কে যদি slug হিসেবে ব্যবহার করতে চান আর যদি rewrite rules গুলোকে specify করে দিতে চান, তাহলে একটা এরে তে নিম্নোক্ত key গুলো দিতে পারেন :
- ‘slug’ (string) এখানে চাইলে আপনার custom slug টি দিতে পারেন। তবে Default হচ্ছে $post_type key.
- ‘with_front’ (bool) কোনো preprend থাকবে কিনা , সেটা এখানে বলতে পারেন। WP_Rewrite::$front. Default true.
- ‘feeds’ (bool) Whether the feed permastruct should be built for এই post type এর জন্য feed থাকবে কিনা? তা এখানে নির্ধারণ করতে পারেন। ডিফল্ট হচ্ছে $has_archive এর value.
- ‘pages’ (bool) pagination থাকবে কিনা সেটা এখানে বলতে পারেন। Default true.
- ‘ep_mask’ (const) Endpoint mask চাইলে assign করতে পারবেন। এখানে যদি কিছু না দেন তাহলে এটি $permalink_epmask থেকে inherits করবে। defaults হচ্ছে EP_PERMALINK.
- ‘query_var’ (string|bool) Sets the query_var key for চাইলে এই post type এর জন্যে query_var key সেট করতে পারেন। Defaults হচ্ছে $post_type key. যদি false দেওয়া হয় , তাহলে একটা post type লোড হতে পারবেনা ?{query_var}={post_slug}. আর যদি query string হয় ?{query_var_string}={post_slug} ভ্যালিড হবে।
- ‘can_export’ (bool) যদি এই post type টি export করার সুযোগ রাখতে চান, তাহলে এখানে true দিতে হবে , আর না চাইলে false দিতে হবে। Default true.
- ‘delete_with_user’ (bool) যেই ইউজার পোস্ট টি তৈরি করেছেন , তাকে ডিলিট করার সাথে সাথে তার তৈরি পোস্ট গুলো ডিলিট হবে কিনা? সেটি এখানে বলে দিতে পারেন। ডিলিট করতে চাইলে true দিতে হবে। আর না চাইলে false দিতে হবে। Default null অর্থাৎ trush ও হবেনা , ডিলিট ও হবেনা।
- ‘_builtin’ (bool) এইটা শুধু মাত্র INTERNAL USE এর জন্য! যদি True দেন, তাহলে native অথবা “built-in” post_type হিসেবে বিবেচিত হবে। Default false.
- ‘_edit_link’ (string) এইটা শুধু মাত্র INTERNAL USE এর জন্য! অর্থাৎ আপনার post type edit link এ ব্যবহারের জন্য একটা URL segment . Default ‘post.php?post=%d’
উদাহরণঃ
উপরে এতক্ষন argument গুলো দেখতে দেখতে নিশ্চই, চোখে দিয়ে ধোঁয়া বের হচ্ছে, বের হওয়ার ই কথা। চলুন এবার ফাঙ্কশন টি ব্যবহার করে একটা Book Manager Plugin তৈরি করে ফেলি।
<?php /* Plugin Name: W3 Book Manager Plugin Plugin URI: https://github.com/w3programmers/w3-book-manager-plugin Description: A plugin to show and manage a list of books. Author: Masud Alam Version: 1.0 Author URI: https://blog.w3programmers.com/ Text Domain: w3-books Domain Path: /languages/ */ function w3_book_manager_init() { $labels = array( 'name' => _x( 'Books', 'Post type general name', 'w3-books' ), 'singular_name' => _x( 'Book', 'Post type singular name', 'w3-books' ), 'menu_name' => _x( 'Books', 'Admin Menu text', 'w3-books' ), 'name_admin_bar' => _x( 'Book', 'Add New on Toolbar', 'w3-books' ), 'add_new' => __( 'Add New', 'w3-books' ), 'add_new_item' => __( 'Add New Book', 'w3-books' ), 'new_item' => __( 'New Book', 'w3-books' ), 'edit_item' => __( 'Edit Book', 'w3-books' ), 'view_item' => __( 'View Book', 'w3-books' ), 'all_items' => __( 'All Books', 'w3-books' ), 'search_items' => __( 'Search Books', 'w3-books' ), 'parent_item_colon' => __( 'Parent Books:', 'w3-books' ), 'not_found' => __( 'No books found.', 'w3-books' ), 'not_found_in_trash' => __( 'No books found in Trash.', 'w3-books' ), 'featured_image' => _x( 'Book Cover Image', 'Overrides the “Featured Image” phrase for this post type. Added in 4.3', 'w3-books' ), 'set_featured_image' => _x( 'Set cover image', 'Overrides the “Set featured image” phrase for this post type. Added in 4.3', 'w3-books' ), 'remove_featured_image' => _x( 'Remove cover image', 'Overrides the “Remove featured image” phrase for this post type. Added in 4.3', 'w3-books' ), 'use_featured_image' => _x( 'Use as cover image', 'Overrides the “Use as featured image” phrase for this post type. Added in 4.3', 'w3-books' ), 'archives' => _x( 'Book archives', 'The post type archive label used in nav menus. Default “Post Archives”. Added in 4.4', 'w3-books' ), 'insert_into_item' => _x( 'Insert into book', 'Overrides the “Insert into post”/”Insert into page” phrase (used when inserting media into a post). Added in 4.4', 'w3-books' ), 'uploaded_to_this_item' => _x( 'Uploaded to this book', 'Overrides the “Uploaded to this post”/”Uploaded to this page” phrase (used when viewing media attached to a post). Added in 4.4', 'w3-books' ), 'filter_items_list' => _x( 'Filter books list', 'Screen reader text for the filter links heading on the post type listing screen. Default “Filter posts list”/”Filter pages list”. Added in 4.4', 'w3-books' ), 'items_list_navigation' => _x( 'Books list navigation', 'Screen reader text for the pagination heading on the post type listing screen. Default “Posts list navigation”/”Pages list navigation”. Added in 4.4', 'w3-books' ), 'items_list' => _x( 'Books list', 'Screen reader text for the items list heading on the post type listing screen. Default “Posts list”/”Pages list”. Added in 4.4', 'w3-books' ), ); $args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'book' ), 'capability_type' => 'post', 'has_archive' => true, 'hierarchical' => false, 'menu_position' => null, 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ), ); register_post_type( 'book', $args ); } add_action( 'init', 'w3_book_manager_init' );
এখন যদি আপনি প্লাগিনটি এক্টিভেট করেন , তাহলে নিচের মতো একটা Book Manager দেখতে পাবেন।
ওয়ার্ডপ্রেসে Post Metadata কি?
Metadata মানে হ’ল data এর data অর্থাৎ তথ্য সম্পর্কিত তথ্য। আর ওয়ার্ডপ্রেসে WordPress Post Metadata ধারা বুঝানো হয় ওয়ার্ডপ্রেসের posts সম্পর্কিত তথ্য।
ওয়ার্ডপ্রেসে Post Metadata এর কাজ কি?
ওয়ার্ডপ্রেসে Post Metadata এর কাজ হচ্ছে একটি সহজ এবং স্ট্যান্ডারাইজড উপায়ে ওয়ার্ডপ্রেসের posts সম্পর্কিত তথ্য গুলোকে wp_postmeta table এর সাহায্যে retrieving এবং manipulating এর কাজগুলোকে সহজ করা। আর এই wp_postmeta table গুলো তার data গুলোকে সাধারণ key-value pair হিসেবে রাখে। আজকের পর্বে আমরা ওয়ার্ডপ্রেসে Post Metadata নিয়ে বিস্তারিত আলোচনা করব।
আর WordPress এর Post Metadata এর Functions গুলো দুইভাগে বিভক্ত:
1. Add/Delete Post Metadata :
2. Get/Update Post Metadata :
add_post_meta()
ওয়ার্ডপ্রেসের wp_postmeta table এ একটা নির্দিষ্ট পোস্টে নতুন meta field (Custom Fields) যুক্ত করার জন্য add_post_meta() function টি ব্যবহৃত হয়।
Syntax
add_post_meta( int $post_id, string $meta_key, mixed $meta_value, bool $unique = false )
Parameters #
- $post_id (int) (Required) যেই পোস্টের এর জন্য meta field তৈরি করতে যাচ্ছেন , তার Post ID এখানে হবে।
- $meta_key (string) (Required) যেই Metadata বা custom field টি তৈরি করবেন , তার name এখানে হবে.
- $meta_value (mixed) (Required) এখানে আপনার Metadata বা custom fielder এর value হবে। তবে value গুলো যদি non-scalar হয় , তাহলে অবশ্যই serializable হতে হবে।
- $unique (bool) (Optional) যদি একই meta key একাধিক meta value এর জন্য ব্যবহার করতে না চান অর্থাৎ , unique রাখতে চান। তাহলে এখানে true দিতে হবে। Default value: false
উদাহরণঃ
<?php add_post_meta( 68, 'my_key', 47 ); //default usage ?>
আর যদি unique রাখতে চান, তাহলে চতুর্থ প্যারামিটারটি true করে দিতে হবে।
<?php add_post_meta( 68, 'my_key', '47', true ); ?>
আবার যদি একই meta key এর বিপরীতে একাধিক meta value রাখতে চান, তাহলে নিচের মতো হবে।
<?php add_post_meta( 68, 'my_key', '47' ); add_post_meta( 68, 'my_key', '682' ); add_post_meta( 68, 'my_key', 'The quick, brown fox jumped over the lazy dog.' ); ?>
delete_post_meta()
ওয়ার্ডপ্রেসের wp_postmeta table থেকে বিদ্যমান যেকোনো meta field (Custom Fields) মুছে ফেলার জন্য delete_post_meta() function টি ব্যবহৃত হয়।
Syntax
delete_post_meta( int $post_id, string $meta_key, mixed $meta_value = '' );
Parameters #
- $post_id (int) (Required) যেই পোস্টের বিপরীতে meta field ডিলিট করতে চাচ্ছেন , তার Post ID এখানে হবে।
- $meta_key (string) (Required) যেই Metadata বা custom field টি delete করবেন , তার name এখানে হবে.
- $meta_value (mixed) (Optional) এখানে চাইলে আপনার Metadata বা custom fielder এর value দিতে পারেন। তবে value গুলো যদি non-scalar হয় , তাহলে অবশ্যই serializable হতে হবে। Default value: ”
উদাহরণঃ
<?php delete_post_meta(76, 'my_key', 'Masud Alam'); ?>
get_post_meta()
ওয়ার্ডপ্রেসের wp_postmeta table থেকে বিদ্যমান যেকোনো meta field (Custom Fields) কে খুঁজে বের করে আনার জন্য get_post_meta() function টি ব্যবহৃত হয়।
Syntax
get_post_meta( int $post_id, string $key = '', bool $single = false )
Parameters #
- $post_id (int) (Required) যেই পোস্টের বিপরীতে meta field খুঁজে বের করতে চাচ্ছেন , তার Post ID এখানে হবে।
- $key (string) (Optional) যদি কোনো specific meta key খুঁজতে চান , তাহলে সেটি এখানে দিতে হয়ে। তবে By default get_post_meta() ফাঙ্কশন সব key গুলো রিটার্ন করে। Default value: ”
$single (bool) (Optional) এখানে যদি true দেন, তাহলে get_post_meta() ফাঙ্কশন আপনাকে একটা নির্দিষ্ট meta key এর শুধু প্রথম value টি return করবে। তবে যদি এই ফাঙ্কশনের দ্বিতীয় প্যারামিটারে কোনো meta key না দেওয়া থাকে , তাহলে এই parameter এর কোনো effect থাকবেনা। Default value: false
উদাহরণঃ
<?php $meta = get_post_meta( get_the_ID() ); //Get the meta for all keys for the current post: $key_1_values = get_post_meta( get_the_ID(), 'key_1' ); //Get all meta for a single key for the current post: $key_1_value = get_post_meta( get_the_ID(), 'key_1', true );//Get the first value of a meta key for the current post: ?>
update_post_meta()
ওয়ার্ডপ্রেসের wp_postmeta table থেকে বিদ্যমান যেকোনো meta field (Custom Fields) পরিবর্তন করার জন্য update_post_meta() function টি ব্যবহৃত হয়। এছাড়া meta field টি বিদ্যমান না থাকলে এটি নতুন একটি meta field যুক্ত করে নিবে। এবং তার ID return করবে। অর্থাৎ, আপনি চাইলে update_post_meta() function কে add_post_meta() ফাঙ্কশনের পরিবর্তে ব্যবহার করতে পারবেন।
Syntax
update_post_meta( int $post_id, string $meta_key, mixed $meta_value, mixed $prev_value = '' )
Parameters #
- $post_id (int) (Required) যেই পোস্টের এর জন্য meta field পরিবর্তন বা নতুন তৈরি করতে যাচ্ছেন , তার Post ID এখানে হবে।
- $meta_key (string) (Required) যেই Metadata বা custom field টি পরিবর্তন বা তৈরি করবেন , তার name এখানে হবে.
- $meta_value (mixed) (Required) এখানে আপনার Metadata বা custom field এর value হবে। তবে value গুলো যদি non-scalar হয় , তাহলে অবশ্যই serializable হতে হবে।
- $prev_value (mixed) (Optional) update এর আগে পূর্বের value check করতে চাইলে , সেটি এখানে দিতে পারেন। Default value: ”
উদাহরণঃ
<?php update_post_meta( $post_id = 76, $key = 'my_key', $value = 'Masud' ); ?>
ওয়ার্ডপ্রেসে Post Metadata function গুলো ব্যবহার করে একটা নতুন প্লাগিন:
এখন আমরা এমন একটা plugin বানাবো , যা দিয়ে একজন ব্যবহারকারী কোনো একটা পোস্ট , মোট কতবার ইতিমধ্যে পড়েছে বা ভিসিট করেছে তা জানতে পারবে। চলুন শুরু করা যাক।
<?php /* Plugin Name: W3 Count Post Visits Plugin URI:https://github.com/w3programmers/w3-count-post-visits Description: W3 Count Number of Visits In a Post Version: 1.0 Author: Masud Alam Author URI:http://www.w3programmers.com/ License: GPLv2 or later Text Domain: w3-count-post-visits Domain Path: /languages/ */ function w3_get_mac(){ // Turn on output buffering ob_start(); //Get the ipconfig details using system commond system('ipconfig /all'); // Capture the output into a variable $mycomsys=ob_get_contents(); // Clean (erase) the output buffer ob_clean(); $find_mac = "Physical"; //find the "Physical" & Find the position of Physical text $pmac = strpos($mycomsys, $find_mac); // Get Physical Address $macaddress=substr($mycomsys,($pmac+36),17); //Display Mac Address return $macaddress; } add_filter( 'the_content', 'w3_add_mac_address' ); function w3_add_mac_address( $content ) { $views=1; $queried_object = get_queried_object(); if($queried_object){ if (get_post_meta($queried_object->ID, w3_get_mac(),true)) { $views=get_post_meta($queried_object->ID, w3_get_mac(),true)+1; update_post_meta( $queried_object->ID, w3_get_mac(),$views); $reading_times="You have already visit this Post ".get_post_meta($queried_object->ID, w3_get_mac(),true)." Times<br>"; return $reading_times.$content; } else{ add_post_meta( $queried_object->ID, w3_get_mac(),$views); $reading_times="You are reading this post for the first time<br>" return $reading_times.content; } } }
ব্যাখ্যা:
পাঠক একটু লক্ষ্য করলেই বুঝতে পারবেন , প্রথমে আমরা লাইন নম্বর ১৪ থেকে ৩৬ এর মধ্যে w3_get_mac() একটি ফাঙ্কশন তৈরি করি, যার কাজ হচ্ছে reader এর computer এর mac address টি খুঁজে বের করবে। তারপর লাইন নাম্বার ৪০ থেকে ৫৫ নম্বর লাইনে আমরা ইউজারের প্রত্যেক বার যে কোনো post ভিজিট করার সময় তার mac address এর বিপরীতে , visit number টি add এবং update করি, আর এই কাজটি করার জন্য আমরা get_post_meta, add_post_meta এবং update_post_meta এই তিনটি ফাঙ্কশন ব্যবহার করি।
এখন যদি আপনি প্লাগিনটি activate করেন ,তাহলে নিচের মতো ফলাফল দেখতে পাবেন।
WordPress এ Meta Box কি?
যখন কোনো ইউজার ওয়ার্ডপ্রেসের কোনো Post তৈরি বা এডিট করতে যায়, তখন সেখানে আমরা কিছু default input fiedlযেমন :Editor, Publish, Categories, Tags ইত্যাদি দেখতে পাই। আর এই box গুলোই হচ্ছে meta boxes. তবে চাইলে আপনিও এইধরণের metabox তৈরি করতে পারেন। যদিও meta box গুলো সাধারণত HTML form elements ই হয়ে থাকে। নিচে ওয়ার্ডপ্রেসের ডিফল্ট Metabox গুলোর একটা ছবি দেওয়া হলো।
কেন আমরা Meta Box গুলো তৈরি করব? #
মূলত ওয়ার্ডপ্রেসে যেকোনো নতুন post তৈরি অথবা বিদ্যমান যেকোনো post এডিট করার সময় ইউজার থেকে post সম্পর্কৃত অতিরিক্ত তথ্য collect করার সহজ এবং সুবিধাজনক মাধ্যম হচ্ছে Meta Box. সাধারণত আপনি যেই Post থেকে অতিরিক্ত তথ্য collect করবেন ,আপনার custom meta box গুলো সেই একই screen এ ই থাকে। তাই সংশ্লিষ্ট পোস্টের সাথে এর রিলেশনটাও ক্লিয়ার থাকে।
Custom Meta box ব্যবহার করে , আপনি যেমন সরাসরি ইউজার থেকে তথ্য নিতে পারেন , আবার চাইলে Meta box গুলোকে hidden রেখেও আপনি উজার থেকে তথ্য নিতে পারেন। এছাড়া ইউজার ও Meta box গুলোকে তাদের স্ক্রিনে যেভাবে ইচ্ছা সেভাবে সাজিয়ে রাখতে পারেন।
কিভাবে আমরা Meta Box গুলো তৈরি করব? #
WordPress এ Meta box গুলো আমরা add_meta_box() ফাঙ্কশনের মাধ্যমে আর WordPress এর ডিফল্ট add_meta_boxes action হুকটি ব্যবহার করে। চলুন প্রথমে add_meta_box() ফাঙ্কশনটি কিভাবে কাজ করে তা দেখা যাক।
add_meta_box() Function Syntax()
add_meta_box( string $id, string $title, callable $callback, string|array|WP_Screen $screen = null, string $context = 'advanced', string $priority = 'default', array $callback_args = null )
Parameters #
- $id (string) (Required) : যেই custom Meta box টি তৈরি করবেন , তার জন্য একটা unique ID এখানে দিতে হবে।
- $title (string) (Required): যেই custom Meta box টি তৈরি করবেন , তার জন্য একটা Title এখানে দিতে হবে।
- $callback (callable) (Required): Meta box এর html content প্রদর্শনের জন্যে একটা callback Function এখানে হবে। আর function এর output এর জন্য অবশ্যই return এর পরিবর্তে echo ব্যবহার করতে হবে।
- $screen (string|array|WP_Screen) (Optional) আপনার custom Meta box টি কোথায় (যেমন: post,page,attachment, ‘link’, নাকি ‘comment’ এ )প্রদর্শন করবেন , তা এখানে চাইলে বলতে পারেন। এখানে আপনি single screen ID, WP_Screen object অথবা screen ID গুলোর জন্য একটা এরে ব্যবহার করতে পারেন। আর by Default এখানে current screen হয়। আপনি যদি নতুন screen তৈরির জন্যে add_menu_page() অথবা add_submenu_page() ব্যবহার করে থাকেন , তাহলে আপনার menu slug কে অবশ্যই sanitize_key() ব্যবহার করতে হবে। অন্যথা ‘screen’ menu সঠিকভাবে আপনার পেজে render নাও করতে পারে। Default value: null
- $context (string) (Optional) এখানে আপনার custom meta box গুলো screen এর কোন জায়গায় প্রদর্শন করবে , তা বলে দিতে পারেন। সাধারণত বিদ্যমান contexts গুলো প্রদর্শনের বেলায় screen to screen vary করে। যেমন Post edit screen এর context গুলোতে ‘normal’, ‘side’, এবং ‘advanced’ এই কয়টি বিদ্যমান থাকে। আবার Comments screen এর context এ ‘normal’ এবং ‘side’ এই দুইটি থাকে, আর Menus meta boxes এ সাধারণত ‘side’ context থাকে। Global Default value: ‘advanced’
- $priority (string) (Optional) : এখানে আপনার meta box এর Priority (‘high’, ‘low’) দিতে পারেন। Default value: ‘default’
- $callback_args (array) (Optional) আপনার callback ফাঙ্কশনের দ্বিতীয় প্যারামিটারের এর জন্য আর্গুমেন্ট গুলোকে একটা array আকারে পাঠাতে পারেন। Default value: null
উদাহরণঃ
এখন আমরা meta box তৈরির উদাহরণ গুলো ধাপে ধাপে দেখব। চলুন শুরু করা যাক।
১. নতুন প্লাগিন কে WordPress এ রেজিস্ট্রেশন
এখনই আমরা সম্পূর্ণ প্লাগিনের কোডগুলো এখানে লিখে ফেলবোনা । বরং আমরা কাজটি ধাপে ধাপে করব । প্রথমে, আমরা “w3-custom-meta-box” নামে একটি ফোল্ডার তৈরি করব। এই ফোল্ডারের মধ্যে, আমরা “w3-custom-meta-box.php” নামে একটি ফাইল তৈরি করব এবং প্লাগিনটিকে ওয়ার্ডপ্রেসে পরিচয় করানোর জন্য সবার উপরে নিম্নোক্ত ডকুমেন্টেশনগুলি রাখব:
<?php /* Plugin Name: W3 Custom Meta Box Plugin URI: https://github.com/w3programmers/w3-custom-meta-box Description: Provides a starting point for creating custom meta boxes. Author: Masud Alam Version: 1.0 Author URI: https://blog.w3programmers.com/ */
2. একটি নতুন Custom Meta box তৈরি
একটি নতুন custom meta box তৈরি করা মোটামুটি সহজ। ইতিমধ্যে আমাদের তৈরি custom-meta-box-template.php ফাইলটিতে নিম্নলিখিত কোডটি লিখব।
/** * Adds a meta box to the post editing screen */ function w3_custom_meta() { add_meta_box( 'w3_meta', __( 'Meta Box Title', 'w3-textdomain' ), 'w3_meta_callback', 'post' ); } add_action( 'add_meta_boxes', 'w3_custom_meta' );
উপরের কোডটিতে আমরা “w3_custom_meta” নামে একটি ফাংশন তৈরি করি, একটি custom meta box তৈরির জন্য এটি “add_meta_boxes” action হুকের (আপনি যদি action hook সম্পর্কে না জেনে থাকেন , তাহলে দয়াকরে আমার এই আর্টিকেল টি পড়ে আসুন। ) সাথে সংযুক্ত করি। এছাড়া উপরের কোডে, আমরা add_meta_box() ফাঙ্কশনের ৭ টি প্যারামিটার এর মধ্যে কেবলমাত্র required চারটি parameter ব্যবহার করেছি। প্যারামিটার গুলো সম্পর্কে আমরা ইতিমধ্যে বিস্তারিত বর্ণনা করেছি।
এবার নতুন Meta box টি পরীক্ষা করার আগে, আমাদেরকে w3_meta_callback callback function টি তৈরি করতে হবে , যা আমাদের Meta box এর আউটপুট দিবে। মনে রাখবেন, পরবর্তী ফাংশনটির নাম অবশ্যই উপরে বর্ণিত $callback প্যারামিটার হিসাবে ব্যবহৃত স্ট্রিংয়ের সাথে মেলে। আমরা এটি যতটুকু পারাযায় সহজ রাখব।
/** * Outputs the content of the meta box */ function w3_meta_callback( $post ) { echo 'This is a meta box'; }
এখন যদি আমরা একটি নতুন পোস্ট তৈরি করতে বা কোনও বিদ্যমান পোস্ট edit করতে যাই তবে আমাদের নতুন মেটা বাক্সটি দেখতে কিছুটা এইরকম দেখাবে।
৩. Meta box এ একটি Form Field যুক্ত করন:
এখন আমরা আমাদের Meta box এ একটা Form Field যুক্ত করব। আর এই কাজটি আমরা আমাদের Meta box তৈরির ফাঙ্কশন অর্থাৎ w3_meta_callback() ফাঙ্কশনের মধ্যেই করব। চলুন w3_meta_callback() ফাঙ্কশনটিকে নিচের মতো আপডেট করে নেই।
/** * Outputs the content of the meta box */ function w3_meta_callback( $post ) { wp_nonce_field( basename( __FILE__ ), 'w3_nonce' ); $w3_stored_meta = get_post_meta( $post->ID ); ?> <p> <label for="meta-text" class="w3-row-title"><?php _e( 'Example Text Input', 'w3-textdomain' )?></label> <input type="text" name="meta-text" id="meta-text" value="<?php if ( isset ( $w3_stored_meta['meta-text'] ) ) echo $w3_stored_meta['meta-text'][0]; ?>" /> </p> <?php }
ব্যাখ্যা:
- প্রথমে আমরা লাইন নম্বর ৫ এ security এর জন্য nonce তৈরি করেছি। (আপনি যদি nonce সম্পর্কে না জেনে থাকেন , তাহলে দয়াকরে আমার এই আর্টিকেল টি পড়ে আসুন। )
- লাইন নম্বর ৬ এ , আমরা get_post_meta () ফাংশনটি ব্যবহার করে $w3_stored_meta variable এ এই পোস্টে সঞ্চিত সমস্ত meta information retrieve করি।
- এবং Finally লাইন নম্বর ১০ এবং ১১ তে, আমাদের একটি label এবং একটি input field রয়েছে। আর label এর মধ্যে “w3-row-title” নামে একটি CSS Class রেখে দিয়েছি। যা পরবর্তীতে আমাদের style এর কাজে ব্যবহার করব। আর $w3_stored_meta variable কে ১১ নম্বর লাইনে অবস্থিত input field এর value হিসেবে প্রদর্শন করি। যেন আগে থেকে সংরক্ষিত value এখানে প্রদর্শন করে।
৪. meta box এর form input কে database এ সংরক্ষণ
এখন আমরা আমাদের meta box এর form input কে database এ সংরক্ষণ করব। তো চলুন শুরু করা যাক :
/** * Saves the custom meta input */ function w3_meta_save( $post_id ) { // Checks save status $is_autosave = wp_is_post_autosave( $post_id ); $is_revision = wp_is_post_revision( $post_id ); $is_valid_nonce = ( isset( $_POST[ 'w3_nonce' ] ) && wp_verify_nonce( $_POST[ 'w3_nonce' ], basename( __FILE__ ) ) ) ? 'true' : 'false'; // Exits script depending on save status if ( $is_autosave || $is_revision || !$is_valid_nonce ) { return; } // Checks for input and sanitizes/saves if needed if( isset( $_POST[ 'meta-text' ] ) ) { update_post_meta( $post_id, 'meta-text', sanitize_text_field( $_POST[ 'meta-text' ] ) ); } } add_action( 'save_post', 'w3_meta_save' );
ব্যাখ্যা:
- লাইন নম্বর ৭-৯ এ আমরা আমাদের current পোস্টের save status চেক করি।
- লাইন নম্বর ১২-১৪ তে আমাদের পোস্টের save status এর ভিত্তিতে script execution কে বন্ধ করে দেই। অর্থাৎ , post টি auto save হয়ে গেছে , কিন্তু nonce valid ছিলোনা।
- লাইন নম্বর ১৭-১৯ এ আমরা আমাদের meta-text নামের meta field এর ডাটা wp_postmeta টেবিল এ সংরক্ষণের ব্যবস্থা করি।
এখন যদি আমরা একটি নতুন পোস্ট তৈরি করতে বা কোনও বিদ্যমান পোস্ট edit করতে যাই এবং কিছু যদি লিখে save করি তবে আমাদের নতুন মেটা বাক্সটি দেখতে কিছুটা এইরকম দেখাবে।
৫. saved meta data এর ব্যবহার
এখন আপনি চাইলে আপনার যেকোনো theme অথবা প্লাগিনে নিচের মতো করে আপনার তৈরি পোস্টের meta field আউটপুট দেখাতে পারেন।
// Retrieves the stored value from the database $w3_meta_value = get_post_meta( get_the_ID(), 'meta-text', true ); // Checks and displays the retrieved value if( !empty( $w3_meta_value ) ) { echo $w3_meta_value; }
৬.Meta box কে পোস্টের সাইডে প্রদর্শন :
এতক্ষন আমাদের তৈরি custom Meta box টি পোস্টের ঠিক নিচে প্রদর্শিত হচ্ছিলো , তবে আমরা চাইলে সেটা পোস্টের right side এ ও প্রদর্শন করতে পারি। সেক্ষেত্রে আপনার add_meta_box() ফাঙ্কশনে ৫ম প্যারামিটারে meta box পজিশন হিসেবে side বলে দিতে হবে। নিচের কোডটি লক্ষ্য করুন।
/** * Adds a meta box to the post editing side screen */ function w3_custom_meta() { add_meta_box( 'w3_meta', __( 'Meta Box Title', 'w3-textdomain' ), 'w3_meta_callback', 'post','side'); } add_action( 'add_meta_boxes', 'w3_custom_meta' );
এখন আপনার meta box এর অবস্থান নিচের মতো হবে :
৭.Meta box কে পেজে প্রদর্শন :
এতক্ষন আমাদের তৈরি custom Meta box টি পোস্টের ঠিক নিচে প্রদর্শিত হচ্ছিলো , তবে আমরা চাইলে সেটা পোস্টের পরিবর্তে পেজেও প্রদর্শন করতে পারি। সেক্ষেত্রে আপনার add_meta_box() ফাঙ্কশনে চতুর্থ প্যারামিটারে post এর পরিবর্তে page বলে দিতে হবে। নিচের কোডটি লক্ষ্য করুন।
/** * Adds a meta box to the page editing screen */ function w3_custom_meta() { add_meta_box( 'w3_meta', __( 'Meta Box Title', 'w3-textdomain' ), 'w3_meta_callback', 'page'); } add_action( 'add_meta_boxes', 'w3_custom_meta' );
meta box content এ CSS styles যুক্ত করন।
আমরা চাইলে আমাদের Metabox Content এ CSS Styles যুক্ত করতে পারি। চলুন প্রথমে আমাদের plugin ফোল্ডারের মধ্যে meta-box-styles.css নামে একটা ফাইল তৈরি করি , তারপর সেখানে নিচের css কোডগুলো যুক্ত করি।
#w3_meta{ overflow: hidden; padding-bottom: 1em; } #w3_meta p{ clear: both; } .w3-row-title{ display: block; float: left; width: 200px; color:red; } .w3-row-content{ float: left; padding-bottom: 1em; } .w3-row-content label{ display: block; line-height: 1.75em; }
এখন আমরা admin_print_styles action হুকে css টিকে একটা ফাঙ্কশন দিয়ে এসাইন করে দিবো। admin_print_styles হুকে এসাইন করা ফাঙ্কশনটি নিচের মতো হবে।
/** * Adds the meta box stylesheet when appropriate */ function w3_admin_styles(){ global $typenow; if( $typenow == 'post' ) { wp_enqueue_style( 'w3_meta_box_styles', plugin_dir_url( __FILE__ ) . 'meta-box-styles.css' ); } } add_action( 'admin_print_styles', 'w3_admin_styles' );
এখন আপনার meta box এর ফলাফল নিচের মতো দেখতে পাবেন।
এবার চলুন আমার একটা custom post type এর মধ্যে কিছু custom metabox তৈরি করি। আর এর জন্য আমরা এখন একটা নতুন প্লাগিন তৈরি করব। যার নাম হবে , W3 Upcoming Events Plugin.প্রথমে চলুন , মূল প্লাগিনের কোড টি দেখাযাক :
<?php /* Plugin Name: W3 Upcoming Events Plugin Plugin URI: https://github.com/w3programmers/w3-upcoming-events-plugin Description: A plugin to show a list of upcoming events on the front-end. Author: Masud Alam Version: 1.0 Author URI: https://blog.w3programmers.com/ Text Domain: w3uep Domain Path: /languages/ */ define( 'ROOT', plugins_url( '', __FILE__ ) ); define( 'IMAGES', ROOT . '/img/' ); define( 'STYLES', ROOT . '/css/' ); define( 'SCRIPTS', ROOT . '/js/' ); function w3uep_custom_post_type() { $labels = array( 'name' => __( 'Events', 'w3uep' ), 'singular_name' => __( 'Event', 'w3uep' ), 'add_new_item' => __( 'Add New Event', 'w3uep' ), 'all_items' => __( 'All Events', 'w3uep' ), 'edit_item' => __( 'Edit Event', 'w3uep' ), 'new_item' => __( 'New Event', 'w3uep' ), 'view_item' => __( 'View Events', 'w3uep' ), 'search_items' => __( 'Search Events', 'w3-w3uep' ), 'not_found' => __( 'No Events Found', 'w3uep' ), 'not_found_in_trash' => __( 'No Events Found in Trash', 'w3uep' ) ); $args = array( 'labels' => $labels, 'public' => true, 'publicly_queryable' => true, 'show_ui' => true, 'show_in_menu' => true, 'query_var' => true, 'rewrite' => array( 'slug' => 'event' ), 'capability_type' => 'post', 'has_archive' => true, 'hierarchical' => false, 'menu_position' => null, 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ), //'show_in_rest' => true // for Gutenberg support ); register_post_type( 'event', $args ); } add_action( 'init', 'w3uep_custom_post_type' ); function w3uep_add_event_info_metabox() { add_meta_box( 'w3uep-event-info-metabox', __( 'Event Info', 'w3uep' ), 'w3uep_render_event_info_metabox', 'event', 'side', 'core' ); } add_action( 'add_meta_boxes', 'w3uep_add_event_info_metabox' ); function w3uep_render_event_info_metabox( $post ) { // generate a nonce field wp_nonce_field( basename( __FILE__ ), 'w3uep-event-info-nonce' ); // get previously saved meta values (if any) $event_start_date = get_post_meta( $post->ID, 'event-start-date', true ); $event_end_date = get_post_meta( $post->ID, 'event-end-date', true ); $event_venue = get_post_meta( $post->ID, 'event-venue', true ); // if there is previously saved value then retrieve it, else set it to the current time $event_start_date = ! empty( $event_start_date ) ? $event_start_date : time(); //we assume that if the end date is not present, event ends on the same day $event_end_date = ! empty( $event_end_date ) ? $event_end_date : $event_start_date; ?> <label for="w3uep-event-start-date"><?php _e( 'Event Start Date:', 'w3uep' ); ?></label> <input class="widefat w3uep-event-date-input" id="w3uep-event-start-date" type="text" name="w3uep-event-start-date" placeholder="Format: February 18, 2014" value="<?php echo date( 'F d, Y', $event_start_date ); ?>" /> <label for="w3uep-event-end-date"><?php _e( 'Event End Date:', 'w3uep' ); ?></label> <input class="widefat w3uep-event-date-input" id="w3uep-event-end-date" type="text" name="w3uep-event-end-date" placeholder="Format: February 18, 2014" value="<?php echo date( 'F d, Y', $event_end_date ); ?>" /> <label for="w3uep-event-venue"><?php _e( 'Event Venue:', 'w3uep' ); ?></label> <input class="widefat" id="w3uep-event-venue" type="text" name="w3uep-event-venue" placeholder="eg. Times Square" value="<?php echo $event_venue; ?>" /> <?php } function w3uep_admin_script_style( $hook ) { global $post_type; if ( ( 'post.php' == $hook || 'post-new.php' == $hook ) && ( 'event' == $post_type ) ) { wp_enqueue_script( 'upcoming-events', SCRIPTS . 'script.js', array( 'jquery', 'jquery-ui-datepicker' ), '1.0', true ); wp_enqueue_style( 'jquery-ui-calendar', STYLES . 'jquery-ui.css', false, '1.10.4', 'all' ); } } add_action( 'admin_enqueue_scripts', 'w3uep_admin_script_style' ); function w3uep_save_event_info( $post_id ) { // checking if the post being saved is an 'event', // if not, then return if ( 'event' != $_POST['post_type'] ) { return; } // checking for the 'save' status $is_autosave = wp_is_post_autosave( $post_id ); $is_revision = wp_is_post_revision( $post_id ); $is_valid_nonce = ( isset( $_POST['w3uep-event-info-nonce'] ) && ( wp_verify_nonce( $_POST['w3uep-event-info-nonce'], basename( __FILE__ ) ) ) ) ? true : false; // exit depending on the save status or if the nonce is not valid if ( $is_autosave || $is_revision || ! $is_valid_nonce ) { return; } // checking for the values and performing necessary actions if ( isset( $_POST['w3uep-event-start-date'] ) ) { update_post_meta( $post_id, 'event-start-date', strtotime( $_POST['w3uep-event-start-date'] ) ); } if ( isset( $_POST['w3uep-event-end-date'] ) ) { update_post_meta( $post_id, 'event-end-date', strtotime( $_POST['w3uep-event-end-date'] ) ); } if ( isset( $_POST['w3uep-event-venue'] ) ) { update_post_meta( $post_id, 'event-venue', sanitize_text_field( $_POST['w3uep-event-venue'] ) ); } } add_action( 'save_post', 'w3uep_save_event_info' ); function w3uep_custom_columns_head( $defaults ) { unset( $defaults['date'] ); $defaults['event_start_date'] = __( 'Start Date', 'w3uep' ); $defaults['event_end_date'] = __( 'End Date', 'w3uep' ); $defaults['event_venue'] = __( 'Venue', 'w3uep' ); return $defaults; } add_filter( 'manage_edit-event_columns', 'w3uep_custom_columns_head', 10 ); function w3uep_custom_columns_content( $column_name, $post_id ) { if ( 'event_start_date' == $column_name ) { $start_date = get_post_meta( $post_id, 'event-start-date', true ); echo date( 'F d, Y', $start_date ); } if ( 'event_end_date' == $column_name ) { $end_date = get_post_meta( $post_id, 'event-end-date', true ); echo date( 'F d, Y', $end_date ); } if ( 'event_venue' == $column_name ) { $venue = get_post_meta( $post_id, 'event-venue', true ); echo $venue; } } add_action( 'manage_event_posts_custom_column', 'w3uep_custom_columns_content', 10, 2 );
এবার আপনার প্লাগিনের js ফোল্ডারে script.js ফাইলে নিচের কোডগুলো লিখুন :
(function( $ ) { $( '#w3uep-event-start-date' ).datepicker({ dateFormat: 'MM dd, yy', onClose: function( selectedDate ){ $( '#w3uep-event-end-date' ).datepicker( 'option', 'minDate', selectedDate ); } }); $( '#w3uep-event-end-date' ).datepicker({ dateFormat: 'MM dd, yy', onClose: function( selectedDate ){ $( '#w3uep-event-start-date' ).datepicker( 'option', 'maxDate', selectedDate ); } }); })( jQuery );
এবং আপনার প্লাগিনের css ফোল্ডারে jquery-ui.css file টি ডাউনলোড করে রাখুন ।
এখন যদি আপনি প্লাগিনটি এক্টিভেট করেন , তাহলে নিচের মতো একটা Upcoming Event Manager দেখতে পাবেন।
: