دوره مجازی پلاگین نویسی وردپرس (جلسه 74) : جلسه پایانی -امنیت در کدنویسی و بررسی درخواست های http و قابلیت ترجمه

- visibility ۲۱ mode_comment

به نام خدا و سلام. با جلسه آخر از دوره پلاگین نویسی وردپرس در خدمت شما هستیم در این جلسه در مورد امن سازی فرم ها و درخواست های ارسال در وردپرس و هم چنین بحث ارسال درخواست های http از نوع get و post و در نهایت در مورد قابلیت ترجمه در پلاگین های وردپرس صحبت خواهیم کرد.

 

info توجه

این مطلب یک جلسه از دوره پلاگین نویسی وردپرس می باشد و برای مشاهده آن باید در دوره ثبت نام کنید.

ثبت نام در دوره پلاگین نویسی وردپرس

comment دیدگاه کاربران
sara salami

خسته نباشید دلاور…
خداقوت پهلوان…

کیوان علی محمدی

نمیدونم حرفتون کنایه ای بود یا نه ولی ممنونم. انشالله که راضی باشید. ^_^

sara salami

استاد پهلوانان فقط کسانی نیستندکه درآوردگاههای میدانهای رزم وورزش حاضرمیشن بلکه کسانی هم که خوب فکرمی کنند،واندیشه های قوی دارندبسیار ارزشمندترند…

masoudrad

با سلام خدمت جناب استاد علی محمدی عزیز.
خیلی سپاسگزارم از به اتمام رساندن این دوره .
امیدوارم همیشه شاد ، تندرست و پیروز باشید.

کیوان علی محمدی

ممنون دوست عزیز و موفق باشید.

سلام. من یه سری داده رو در جدول posts ذخیره کردم و حالا میخوام در پنل مدیریت برای ادمین خروجی بگیرم و به صورت جدولی نمایش بدم همانند لیست نوشته ها. از طریق
class Declare_Device_List_Table extends WP_List_Table
میخوام این کار رو انجام بدم. یک تابع داخل این کلاس نوشتم که داده ها رو از جدول posts میگیره اما نمیدونم درون این تابع میشه از
$results = new WP_Query( $args );
استفاده کرد یا نه؟ من نوشتم اما خروجی نمیتونم بگیرم. لطفا راهنمایی کنید و یه نمونه کد کوتاه در این مورد بذارید.

کیوان علی محمدی

سلام دوست عزیز.
http://wpengineer.com/2426/wp_list_table-a-step-by-step-guide/

چطوری باید از wp_query داخل یه کلاس دیگه استفاده کرد؟

<?php
if(!class_exists(‘WP_List_Table’)){
    require_once( ABSPATH . ‘wp-admin/includes/class-wp-list-table.php’ );
}

/************************** CREATE A PACKAGE CLASS *****************************/
class Declare_Device_List_Table extends WP_List_Table {

    var $example_data = array(
            array(
                ‘ID’        => 1,
                ‘title’     => ‘300’,
                ‘rating’    => ‘R’,
                ‘director’  => ‘Zach Snyder’
            ),
            array(
                ‘ID’        => 2,
                ‘title’     => ‘Eyes Wide Shut’,
                ‘rating’    => ‘R’,
                ‘director’  => ‘Stanley Kubrick’
            ),
            array(
                ‘ID’        => 3,
                ‘title’     => ‘Moulin Rouge!’,
                ‘rating’    => ‘PG-13’,
                ‘director’  => ‘Baz Luhrman’
            ),
            array(
                ‘ID’        => 4,
                ‘title’     => ‘Snow White’,
                ‘rating’    => ‘G’,
                ‘director’  => ‘Walt Disney’
            ),
            array(
                ‘ID’        => 5,
                ‘title’     => ‘Super 8’,
                ‘rating’    => ‘PG-13’,
                ‘director’  => ‘JJ Abrams’
            ),
            array(
                ‘ID’        => 6,
                ‘title’     => ‘The Fountain’,
                ‘rating’    => ‘PG-13’,
                ‘director’  => ‘Darren Aronofsky’
            ),
            array(
                ‘ID’        => 7,
                ‘title’     => ‘Watchmen’,
                ‘rating’    => ‘R’,
                ‘director’  => ‘Zach Snyder’
            ),
            array(
                ‘ID’        => 8,
                ‘title’     => ‘2001’,
                ‘rating’    => ‘G’,
                ‘director’  => ‘Stanley Kubrick’
            ),
        );


    /** ************************************************************************/
    function __construct(){
        global $status, $page;
                
        //Set parent defaults
        parent::__construct( array(
            ‘singular’  => ‘device’,     //singular name of the listed records
            ‘plural’    => ‘devices’,    //plural name of the listed records
            ‘ajax’      => false        //does this table support ajax?
        ) );
        
    }


    /** ************************************************************************
     * WP_List_Table::single_row_columns()
     * 
     * @param array $item A singular item (one full row’s worth of data)
     * @param array $column_name The name/slug of the column to be processed
     * @return string Text or HTML to be placed inside the column <td>
     **************************************************************************/
    function column_default($item, $column_name){
        switch($column_name){
            case ‘author’:
            case ‘date’:
                return $item[$column_name];
            default:
                return print_r($item,true); //Show the whole array for troubleshooting purposes
        }
    }


    /** ************************************************************************ 
     * @see WP_List_Table::::single_row_columns()
     * @param array $item A singular item (one full row’s worth of data)
     * @return string Text to be placed inside the column <td> (device title only)
     **************************************************************************/
    function column_title($item){
        
        //Build row actions
        $actions = array(
            ‘edit’      => sprintf(‘<a href="?page=%s&action=%s&device=%s">Edit</a>’,$_REQUEST[‘page’],’edit’,$item[‘ID’]),
            ‘delete’    => sprintf(‘<a href="?page=%s&action=%s&device=%s">Delete</a>’,$_REQUEST[‘page’],’delete’,$item[‘ID’]),
        );
        
        //Return the title contents
        return sprintf(‘%1$s <span style="color:silver">(id:%2$s)</span>%3$s’,
            /*$1%s*/ $item[‘author’],
            /*$2%s*/ $item[‘ID’],
            /*$3%s*/ $this->row_actions($actions)
        );
    }


    /** ************************************************************************ 
     * @see WP_List_Table::::single_row_columns()
     * @param array $item A singular item (one full row’s worth of data)
     * @return string Text to be placed inside the column <td> (device title only)
     **************************************************************************/
    function column_cb($item){
        return sprintf(
            ‘<input type="checkbox" name="%1$s[]" value="%2$s" />’,
            /*$1%s*/ $this->_args[‘singular’],  //Let’s simply repurpose the table’s singular label ("device")
            /*$2%s*/ $item[‘ID’]                //The value of the checkbox should be the record’s id
        );
    }


    /** ************************************************************************
     * @see WP_List_Table::::single_row_columns()
     * @return array An associative array containing column information: ‘slugs’=>’Visible Titles’
     **************************************************************************/
    function get_columns(){
        $columns = array(
            ‘cb’        		=> ‘<input type="checkbox" />’, //Render a checkbox instead of text
            ‘author’     		=> ‘نام کاربر’,
            ‘date’    			=> ‘تاریخ ثبت درخواست’,
            ‘client_name’  		=> ‘نام مشتری’,
			‘subscriber_number’	=> ‘شماره اشتراک’,
			‘description’		=> ‘توضیحات’,
        );
        return $columns;
    }


    /** ************************************************************************
     * @return array An associative array containing all the columns that should be sortable: ‘slugs’=>array(‘data_values’,bool)
     **************************************************************************/
    function get_sortable_columns() {
        $sortable_columns = array(
            ‘author’     		=> array(‘author’,false),     //true means it’s already sorted
            ‘date’    			=> array(‘date’,false),
            ‘client_name’  		=> array(‘client_name’,false),
			‘subscriber_number’ => array(‘subscriber_number’,false),
			‘description’  		=> array(‘description’,false),
        );
        return $sortable_columns;
    }


    /** ************************************************************************
     * @return array An associative array containing all the bulk actions: ‘slugs’=>’Visible Titles’
     **************************************************************************/
    function get_bulk_actions() {
        $actions = array(
            ‘delete’    => ‘Delete’
        );
        return $actions;
    }


    /** ************************************************************************
     * Optional. You can handle your bulk actions anywhere or anyhow you prefer.
     * For this example package, we will handle it in the class to keep things
     * clean and organized.
     * 
     * @see $this->prepare_items()
     **************************************************************************/
    function process_bulk_action() {
        
        //Detect when a bulk action is being triggered…
        if( ‘delete’===$this->current_action() ) {
            wp_die(‘Items deleted (or they would be if we had items to delete)!’);
        }
        
    }
	
	function table_data(){
		global $wpdb;
		$table_name = $wpdb->prefix . ‘posts’;
		$data=array();
		
		/*$results = $wpdb->get_results( "SELECT * FROM $table_name WHERE post_type = ‘declare_device’" );
		$vid = array();
		$author = array();
		$date = array();
		$client_name = array();
		$subsriber_number = array();
		$description = array();
		$i = 0;
		foreach( $results as $result ){
			$vid[] = $result->post->ID;
			$author[] = $result->post_author;
			$date[] = $result->post_date;
			$client_name[] = get_post_meta( $vid , ‘client_name’ , true);
			$subscriber_name[] = get_post_meta( $vid , ‘subsriber_number’ , true);
			$description[] = $result->post_content;
			$data[] = array(
				‘ID’ => $vid[$i],
				‘author’ => $author[$i],
				‘date’ => $date[$i],
				‘client_name’ => $client_name[$i],
				‘subscriber_name’ => $subscriber_name[$i],
				‘description’ => $description[$i],
			);
			$i++;
		}*/
		$args = array(
			‘post_type’ => ‘declare_device’,
		);
		$vid = array();
		$author = array();
		$date = array();
		$client_name = array();
		$subsriber_number = array();
		$description = array();
		$i = 0;
		$results = new  WP_Query( $args );
		echo $result->request;
		if( $results->have_posts() ){
			while( $results->have_posts() ){
				$results->the_post();
				$vid[] = $results->post->ID;
				$author[] = get_the_author();
				$date[] = get_the_date();
				$client_name[] = get_post_meta( $vid , ‘client_name’ , true);
				$subscriber_name[] = get_post_meta( $vid , ‘subsriber_number’ , true);
				$description[] = get_the_content();
				$data[] = array(
					‘ID’ => $vid[$i],
					‘author’ => $author[$i],
					‘date’ => $date[$i],
					‘client_name’ => $client_name[$i],
					‘subscriber_number’ => $subscriber_number[$i],
					‘description’ => $description[$i],
				);
			}
		}
		else{
			echo ‘<tr class="no-items"><td class="colspanchange" colspan="5">هیچ گزارشی ثبت نشده است.</td></tr>’;
		}
		wp_reset_postdata();
 
        return $data;
	}
    /** ************************************************************************
     * REQUIRED! This is where you prepare your data for display. This method will
     * usually be used to query the database, sort and filter the data, and generally
     * get it ready to be displayed. At a minimum, we should set $this->items and
     * $this->set_pagination_args(), although the following properties and methods
     * are frequently interacted with here…
     * 
     * @global WPDB $wpdb
     * @uses $this->_column_headers
     * @uses $this->items
     * @uses $this->get_columns()
     * @uses $this->get_sortable_columns()
     * @uses $this->get_pagenum()
     * @uses $this->set_pagination_args()
     **************************************************************************/
    function prepare_items() {
        global $wpdb;
        
        $per_page = 5;
        
        $columns = $this->get_columns();
        $hidden = array();
        $sortable = $this->get_sortable_columns();
        
        $this->_column_headers = array($columns, $hidden, $sortable);
        
        $this->process_bulk_action();
        
        $data = $this->table_data();
        
        function usort_reorder($a,$b){
            $orderby = (!empty($_REQUEST[‘orderby’])) ? $_REQUEST[‘orderby’] : ‘title’; //If no sort, default to title
            $order = (!empty($_REQUEST[‘order’])) ? $_REQUEST[‘order’] : ‘asc’; //If no order, default to asc
            $result = strcmp($a[$orderby], $b[$orderby]); //Determine sort order
            return ($order===’asc’) ? $result : -$result; //Send final sort direction to usort
        }
        usort($data, ‘usort_reorder’);

        $current_page = $this->get_pagenum();

        $total_items = count($data);

        $data = array_slice($data,(($current_page-1)*$per_page),$per_page);

        $this->items = $data;

        $this->set_pagination_args( array(
            ‘total_items’ => $total_items,                  //WE have to calculate the total number of items
            ‘per_page’    => $per_page,                     //WE have to determine how many items to show on a page
            ‘total_pages’ => ceil($total_items/$per_page)   //WE have to calculate the total number of pages
        ) );
    }


}

/** ************************ REGISTER THE TEST PAGE ****************************/
function add_menu_declare_device(){
	add_menu_page(‘اعلام غیرقابل تعمیر بودن دستگاه’, ‘اعلام غیرقابل تعمیر بودن دستگاه’, ‘manage_options’, ‘page_declare_device’, ‘render_list_declare_device’, ‘dashicons-dismiss’, 19);
} 
add_action(‘admin_menu’, ‘add_menu_declare_device’);

/** *************************** RENDER TEST PAGE ********************************/
function render_list_declare_device(){
    
    //Create an instance of our package class…
    $testListTable = new Declare_Device_List_Table();
    //Fetch, prepare, sort, and filter our data…
    $testListTable->prepare_items();
    
    ?>
    <div class="wrap">
        
        <div id="icon-users" class="icon32"><br/></div>
        <h2>لیست درخواست اعلام غیرقابل تعمیر بودن دستگاه</h2>
        
        <!– Forms are NOT created automatically, so you need to wrap the table in one to use features like bulk actions –>
        <form id="devices-filter" method="get">
            <!– For plugins, we also need to ensure that the form posts back to our current page –>
            <input type="hidden" name="page" value="<?php echo $_REQUEST[‘page’] ?>" />
            <!– Now we can render the completed list table –>
            <?php $testListTable->display() ?>
        </form>
        
    </div>
    <?php
}
کیوان علی محمدی

سلام دوست عزیز.در تابع prepare_items می تونید کلاس رو خوانی کنید و داده هاتون رو بگیرین.

سلام.
من یه سوال در مورد یکی از پلاگین های وردپرس دارم. ممنون میشم بهم جواب بدین.
پلاگین Parsi Date که برای فارسی کردن تاریخ و اعداد استفاده میشه رو نصب کردم ولی توی قسمت اطلاعات پست ها و توی بلاک های قالبم، اسم ماه ها رو ناقص نشون میده (مثلاً اردیبهشت رو نشون میده ارد) کلاً 3 حرفی نشون میده. میتونین راهنمایی کنید که چطور میشه مشکلشو حل کرد؟
با تشکر

کیوان علی محمدی

سلام دوست عزیز. از بخش تنظیمات همگانی می تونید این مورد رو تغییر بدین.

سلاک. من یه آریا رو در جدول با استفاده از تابع maybe_serialize ذخیره کردم. اما وقتی میخوام اونو با تابع maybe_unserialize مجدد فراخوانی کنم خطا میگیره و مقدار false برمیگردونه
توی سایت http://www.unserialize.com هم که مقداری که از دیتابیس واکشی میکنم رو وارد میکنم باز هم همون حالت serislize رو برمیگردونه
مقداری که توی دیتابیس ذخیره شده اینه:
a:5:{s:3:”pid”;i:72;s:3:”qty”;i:12;s:5:”width”;d:3;s:5:”title”;s:17:”jdy”;s:5:”price”;s:5:”45000″;}

کیوان علی محمدی

سلام به چه روشی ذخیره کردین؟

Reza Zabet

سلام وقت بخیر …. بعد از دیدن این آموزش یعنی میتونیم هر پلاگینی رو دستکاری کرد و تغییراتی رو ایجاد کرد مثلا من از طریق فرم ساز گراویتی فرم پرداخت درست کردم ولی پرداخت کاربر در پروفایلش که از طریق افزونه upme ایجاد کردم ثبت نمیشه حالا بعد از دیدن این آموزش میشه همچنین کاری رو انجام داد؟ مرسی

کیوان علی محمدی

سلام مطئنا توانایی ویرایش پلاگین ها رو می تونید کسب کنید. نکته اینجاست که چقدر تمرین کردین و مهارت بدست آوردین. چون ویرایش پلاگین های بزرگ کار آسونی نیستش.

چرا پیام منو تایید نمیکنید

کیوان علی محمدی

تایید شد.

سلام استاد. من مدتهاست که دنبال راه خلی برای مشکلم میگردم اما پیداش نکردم. لطفا کمک کنید.
این کدی که نوشتم توی کروم به درستی کار میکنه اما توی فایرفاکس نمیتونم خروجی بگیرم.

صفحه html
<?php
if(!defined(‘ABSPATH’))
	exit(‘No Access!’);

if ( !is_user_logged_in() ) 
{
    wp_redirect(  home_url() );
}

global $post,$wpdb;

if(isset($_POST[‘catID’]))
	$category = $_POST[‘catID’];

if(!empty($_POST[‘catID’]))
{
	$args = array(
		‘posts_per_page’   => -1 ,
		‘post_type’        => ‘product’,
		‘post_status’      => ‘publish’,
		‘tax_query’ => array(
			array(
				‘taxonomy’ => ‘product_cat’,
				‘field’ => ‘id’,
				‘terms’ => $category
		)
	));
}
else
{
	$args = array(
		‘posts_per_page’   => -1 ,
		‘post_type’        => ‘product’,
		‘post_status’      => ‘publish’);
}

$results = new WP_Query ($args);
?>

<div class="wrap">
	<h1 class="wp-heading-inline">سفارش محصول</h1>
	<a class="page-title-action" href="<?php echo admin_url( ‘admin.php?page=wporder_add_cart’ ); ?>">مشاهده سبد خرید</a>
	<hr class="wp-header-end">
	<div id="message"></div>
	<div class="tablenav top">
		<div class="alignleft actions bulkactions">
			<form method="post">
				<select id="catID" name="catID" >
					<option value="0"><?php echo esc_attr(__(‘Select Category’)); ?></option>
					<?php
					$categories = get_terms(‘product_cat’);
					foreach ($categories as $category) { ?>
						<option value="<?php echo $category->term_id; ?>">
						<?php echo $category->name; ?>
						<?php echo ($category->count); ?>
						</option>
					<?php } ?>
				</select>
				<button type="submit" id="order_search_cat_id" class="btn btn-primary">جستجو</button>
			</form>
		</div>
	</div>
	<form method="post" id="form_new_order">
		<table class="wp-list-table widefat fixed striped posts">
			<thead>
				<tr>
					<th scope="col" class="manage-column">کد کالا</th>
					<th scope="col" class="manage-column">نام کالا</th>
					<th scope="col" class="manage-column">عرض دهانه (متر)</th>
					<th scope="col" class="manage-column">تعداد</th>
					<th scope="col" class="manage-column">قیمت واحد (تومان)</th>
					<th scope="col" class="manage-column"></th>
				</tr>
			</thead>
				
			<tbody>
				<?php if ( $results->have_posts() ):
					while ( $results->have_posts() ):
						$results->the_post();
						$product_id = $results->post->ID;?>

						<tr>
							<td><?php echo get_post_meta($product_id,’code_product’, true); ?></td>
							<td><?php echo get_the_title(); ?></td>
							<td>
							<?php 
								$width_door = get_post_meta($product_id,’width_door’, true); 
								if( $width_door == "enable" ){
							?>
							<input type="text" id="width_<?php echo $product_id; ?>" name="width_door" value="">
							<?php } else { ?>
								<input type="hidden" id="width_<?php echo $product_id; ?>" value="0">
								<p> —- </p>
							<?php } ?>
							</td>
							<td><input type="text" id="qty_<?php echo $product_id; ?>" name="quantity" min="1" value="1"></td>
							<td><?php echo number_format(get_post_meta($product_id,’price_product’, true)); ?> تومان </td>
							<?php //wp_nonce_field( ‘add_cart_ajax_nonce’, ‘order-security-add-cart’ ); ?>
							<td><button data-prodid="<?php echo $product_id; ?>" class="add_to_cart" href=""><span class="dashicons dashicons-plus"></span></button></td>
						</tr>
					<?php endwhile;
				endif;
				wp_reset_postdata();?>
			</tbody>
		</table>
****************************************************
صفحه js
$(".add_to_cart").click( function(e) {
			
            event.preventDefault();
			
			var $this 	= $(this);
			var prodid 	= $this.attr(‘data-prodid’);
			var qty		= $("#qty_"+prodid).val(),
				width	= $("#width_"+prodid).val();
			
			$.ajax({
                type: ‘POST’,
                url: ajaxURL,
                dataType: ‘json’,
                data: {
                    ‘action’    : ‘wporder_ajax_addcart’,
					‘prodid’	: prodid,
                    ‘qty’   	: qty,
					‘width’		: width
                },
                beforeSend: function( ) {
                    $this.children(‘i’).remove();
                    $this.prepend(‘<i class="fa-left ‘+process_loader_spinner+’"></i>’);
                },

                success: function(data) {
                    if( data.success ) {
                        jQuery(‘#message’).empty().append(‘<div class="alert alert-success alert-dismissible" role="alert"><button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>’+ data.msg +'</div>’);
                    } else {
                        jQuery(‘#message’).empty().append(‘<div class="alert alert-danger alert-dismissible" role="alert"><button type="button" class="close" data-hide="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>’+ data.msg +'</div>’);
                    }
                },
                error: function(errorThrown) {

                },
                complete: function(){
                    $this.children(‘i’).removeClass(process_loader_spinner);
                    $this.children(‘i’).addClass(success_icon);
                }
            });
		});
/*********************************************/
صفحه ajax
add_action( ‘wp_ajax_wporder_ajax_addcart’, ‘wporder_ajax_addcart’ );
if( !function_exists(‘wporder_ajax_addcart’) ){
	function wporder_ajax_addcart(){
		global $wpdb;
		$current_user = wp_get_current_user();
		$userID       =  $current_user->ID;
		
        $pid 	= intval($_POST[‘prodid’]);
		$qty 	= intval($_POST[‘qty’]);
		$width 	= floatval($_POST[‘width’]);
		
		$query = $wpdb -> get_row ( "SELECT * FROM $wpdb->posts WHERE $wpdb->posts.ID = ".$pid."" , OBJECT );
		
		$title = $query -> post_title;
		$price = get_post_meta ( $pid, ‘price_product’, true );
		$data = array( 
			‘pid’ => $pid, 
			‘qty’ => $qty, 
			‘width’ => $width, 
			‘title’ => $title, 
			‘price’ => $price
		);
		
		$result = $wpdb->insert( 
			$wpdb->prefix.’cart_sessions’, 
			array( 
				‘session_key’ => $userID, 
				‘session_value’ => maybe_serialize( $data ),
				‘session_expiry’ => time() + 60 * 60 * 24
			), 
			array( 
				‘%s’,
				‘%s’,
				‘%d’
			) 
		);
		if( $result ){
			echo json_encode( array( ‘success’ => true, ‘msg’ => esc_html__(‘محصول "’.$title.’" به سبد خرید اضافه شد.’) ) );
			die();
		}
		else{
			echo json_encode( array( ‘error’ => true, ‘msg’ => esc_html__(‘خطایی در هنگام عملیات رخ داده است. لطفا مجددا تلاش کنید.’) ) );
			die();
		}
	}
}
کیوان علی محمدی

سلام. کدتون و ایمیل کنید لطفا. اینطوری قابل خوندن نیست.

سلام.یک سوال داشتم.برای این دوره php در سطح متوسط کافیه؟یا باید حرفه ای بلد بود؟

کیوان علی محمدی

سلام در سطح متوسط کافیه.

نیاز به لاگین

برای ارسال دیدگاه و یا پرسیدن سوال خود در این قسمت، باید در سایت لاگین شوید.