קטגוריות
ווקומרס

עמלת סבלות בווקומרס

איך לחייב בחירת משלוח עבור קטגוריה מסוימת, להוסיף אפשרות לסבלות, ולהציג את זמן האספקה?

add_filter( 'woocommerce_checkout_fields', 'conldess_add_fields' );
add_action( 'woocommerce_cart_calculate_fees', 'condless_add_checkout_fee' );
add_filter( 'woocommerce_package_rates', 'condless_set_shipping_methods', 10, 2 );
add_action( 'woocommerce_review_order_before_submit', 'condless_add_lead_time' );
add_filter( 'woocommerce_email_order_meta_fields', 'condless_add_email_order_meta_fields', 10, 3 );
add_action( 'woocommerce_thankyou', 'condless_display_order_meta' );
add_action( 'woocommerce_view_order', 'condless_display_order_meta' );
add_action( 'woocommerce_admin_order_data_after_billing_address', 'condless_admin_display_order_meta' );

function conldess_add_fields( $fields ) {
	$fields['billing']['billing_floor'] = [
		'label'		=> __( 'Floor', 'woocommerce' ),
		'required'	=> true,
		'priority'	=> $fields['billing']['billing_address_1']['priority'] + 2,
		'type'		=> 'number',
		'class'		=> [ 'update_totals_on_change' ],
		'custom_attributes'	=> [ 'min' => 0 ],
	];
	$fields['billing']['billing_elevator'] = [
		'label'		=> __( 'Elevator', 'woocommerce' ),
		'required'	=> true,
		'priority'	=> $fields['billing']['billing_floor']['priority'] + 2,
		'type'		=> 'select',
		'options'	=> [ 'no' => 'no', 'yes' => 'yes' ],
		'default'	=> 'no',
		'class'		=> [ 'update_totals_on_change' ],
	];
 	$fields['billing']['billing_porterage'] = [
		'label'		=> __( 'Porterage', 'woocommerce' ),
		'required'	=> true,
		'priority'	=> $fields['billing']['billing_elevator']['priority'] + 2,
		'type'		=> 'select',
		'options'	=> [ 'no' => 'without', 'yes' => 'include' ],
		'default'	=> 'no',
		'class'		=> [ 'update_totals_on_change' ],
	];
	?>
		<script type="text/javascript">
		jQuery( function( $ ) {
			$( '#billing_floor' ).on( 'keyup change', function() {
				$( 'body' ).trigger( 'update_checkout' );
			} );
		} );
		</script>
	<?php
	return $fields;
}

function condless_add_checkout_fee() {
	$elevator_fee = 10;
	$price_per_floor = 20;
	if ( ! ( is_admin() && ! wp_doing_ajax() ) && false === strpos( WC()->session->get( 'chosen_shipping_methods' )[0], 'local_pickup' ) ) {
		if ( isset( $_POST['post_data'] ) ) {
			parse_str( $_POST['post_data'], $post_data );
		} else {
			$post_data = $_POST;
		}
		if ( ! empty( $post_data['billing_floor'] ) && ! empty( $post_data['billing_elevator'] ) && ! empty ( $post_data['billing_porterage'] ) && 'yes' === $post_data['billing_porterage'] ) {
			WC()->cart->add_fee( __( 'Porterage', 'woocommerce' ), 'yes' === $post_data['billing_elevator'] ? $elevator_fee : $price_per_floor * $post_data['billing_floor'], true );
		}
	}
}

function condless_set_shipping_methods( $rates, $package ) {
	$pickup_only_cat = [ 'general' ];
	$cart_cat = [];
	foreach ( wc()->cart->get_cart() as $cart_item ) {
		$cart_cat = array_merge( $cart_cat, wp_get_post_terms( $cart_item['product_id'], 'product_cat', [ 'fields' => 'names' ] ) );
	}
	if ( array_intersect( $cart_cat, $pickup_only_cat ) ) {
		foreach ( $rates as $rate_id => $rate ) {
			if ( 'local_pickup' !== $rate->method_id ) {
				unset( $rates[ $rate_id ] );
			}
		}
	}
	return $rates;
}

function condless_add_lead_time() {
	$cat_14 = [ 'general' ];
	$lead_time = '1 business day';
	$cart_cat = [];
	foreach ( wc()->cart->get_cart() as $cart_item ) {
		$cart_cat = array_merge( $cart_cat, wp_get_post_terms( $cart_item['product_id'], 'product_cat', [ 'fields' => 'names' ] ) );
	}
	if ( array_intersect( $cart_cat, $cat_14 ) ) {
		$lead_time = '14 business days';
	} ?>
		<table class="woocommerce-table shop_table gift_info">
			<tbody>
				<tr>
					<th><?php _e( 'Lead time', 'woocommerce' ); ?></th>
					<td><?php echo $lead_time; ?></td>
				</tr>
			</tbody>
		</table>
<?php }

function condless_add_email_order_meta_fields( $fields, $sent_to_admin, $order_obj ) {
	$fields['billing_floor'] = [
		'label'	=> __( 'Floor', 'woocommerce' ),
		'value'	=> get_post_meta( $order_obj->get_order_number(), '_billing_floor', true ),
	];
	$fields['billing_elevator'] = [
		'label'	=> __( 'Elevator', 'woocommerce' ),
		'value'	=> 'yes' === get_post_meta( $order_obj->get_order_number(), '_billing_elevator', true ) ? 'yes' : 'no',
	];
	$fields['billing_porterage'] = [
		'label'	=> __( 'Porterage', 'woocommerce' ),
		'value'	=> 'yes' === get_post_meta( $order_obj->get_order_number(), '_billing_porterage', true ) ? 'include' : 'without',
	];
	return $fields;
}

function condless_admin_display_order_meta( $order ) {
	echo '<strong>' . __( 'Floor', 'woocommerce' ) . '</strong> ' . get_post_meta( $order->get_id(), '_billing_floor', true ) . '. <strong>' . __( 'Elevator', 'woocommerce' ) . '</strong> ' . ( 'yes' === get_post_meta( $order->get_id(), '_billing__levator', true ) ? 'yes' : 'no' ) . '. <strong>' . __( 'Porterage', 'woocommerce' ) . '</strong> ' . ( 'yes' === get_post_meta( $order->get_id(), '_billing_porterage', true ) ? 'include' : 'without' );
}

function condless_display_order_meta( $order_id ) {
	echo '<strong>' . __( 'Floor', 'woocommerce' ) . '</strong> ' . get_post_meta( $order_id, '_billing_floor', true ) . '. <strong>' . __( 'Elevator', 'woocommerce' ) . '</strong> ' . ( 'yes' === get_post_meta( $order_id, '_billing__levator', true ) ? 'yes' : 'no' ) . '. <strong>' . __( 'Porterage', 'woocommerce' ) . '</strong> ' . ( 'yes' === get_post_meta( $order_id, '_billing_porterage', true ) ? 'include' : 'without' );
}
קטגוריות
ווקומרס

אבטחת ווקומרס

וחדר הסודות.

שיפור אבטחת המערכת ברמת הוורדפרס:

  • אבטח את השרת
  • הענק הרשאות: 755 לתיקיות, 644 לקבצים
  • עדכן באופן תדיר
  • התקן תוספים מעטים ככל האפשר
  • דווח על כל פעילות חשודה בחשבון לספק האחסון שלכם
  • השתמש בכלי המובנה "בריאות אתר"
  • הסר תבניות שלא בשימוש
  • התקן תעודת SSL
  • השתמש במשתמש מסוג "עורך" והתחבר לאדמין רק בעת הצורך
  • ביטול עורך התבניות המובנה בלוח הבקרה- הוסף לקובץ wp-config.php את ההוראה:
define( 'DISALLOW_FILE_EDIT', true );
  • מניעת אופציית הדפדוף בתיקיות, גישה לקבצים ותיקיות חשובים, והתקפות XSS- הוסף לקובץ htaccess. את ההוראות:
Options -Indexes

<FilesMatch "^.*(xmlrpc.php|error_log|wp-config\.php|php.ini|\.[hH][tT][aApP].*)$">
Order deny,allow
Deny from all
</FilesMatch>

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
# Comment the following directive if multisite
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L] 
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]
</IfModule>

RewriteCond %{HTTP_USER_AGENT} (libwww-perl|wget|python|nikto|curl|scan|java|winhttp|clshttp|loader) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} (;|<|>|'|"|\)|\(|%0A|%0D|%22|%27|%28|%3C|%3E|%00).*(libwww-perl|wget|python|nikto|curl|scan|java|winhttp|HTTrack|clshttp|archiver|loader|email|harvest|extract|grab|miner) [NC,OR]
RewriteCond %{THE_REQUEST} \?\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} \/\*\ HTTP/ [NC,OR]
RewriteCond %{THE_REQUEST} etc/passwd [NC,OR]
RewriteCond %{THE_REQUEST} cgi-bin [NC,OR]
RewriteCond %{THE_REQUEST} (%0A|%0D) [NC,OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC,OR]
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
RewriteCond %{QUERY_STRING} (\.\./|\.\.) [OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} http\: [NC,OR] 
RewriteCond %{QUERY_STRING} https\: [NC,OR]
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR] 
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>).* [NC,OR]
RewriteCond %{QUERY_STRING} (NULL|OUTFILE|LOAD_FILE) [OR]
RewriteCond %{QUERY_STRING} (\./|\../|\.../)+(motd|etc|bin) [NC,OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC,OR]
RewriteCond %{QUERY_STRING} (sp_executesql) [NC]
RewriteRule ^(.*)$ - [F,L]
  • ביטול אפשרות להרצת PHP- צור קובץ htaccess. בתיקיית ההעלאות עם התוכן:
<Files "*.php">
Order Deny,Allow
Deny from All
</Files>
  • הסתרת גרסת הוורדפרס ושגיאות התחברות- הוסף לקובץ functions.php שבתבנית הבת:
add_filter( 'the_generator', '__return_false' );
add_filter( 'login_errors', create_function( '$a', "return 'Invalid Input';" ) );
  • סרוק באופן תדיר את הקוד בתיקיית הוורדפרס ובבסיס הנתונים לאיתור נוזקות ומחק פריטים מיותרים, בצע גיבוי מלא לפני כל שינוי, שקול להתקין את וורדפרס מחדש דרך לוח הבקרה (קבצי הליבה, התבניות והתוספים), היעזר בפקודה למציאת הקבצים ששונו לאחרונה:
find ./ -type f -mtime -15

הסרת נוזקת הפרסומות הקופצות במובייל- מחק את הקבצים wp-tmp.php ,wp-vcd.php ,wp-feed.php מהתיקיה wp-includes, ואת הקוד שיוצר אותם מהקובץ functions.php שבתבניות.

הסרת נוזקת Japanese Keyword Hack- נקה את הקוד הזדוני מהקבצים htaccess. ,wp-config.php ,sitemap.xml ומתיקיית ההעלאות.

כפי שבוודאי שמת לב- מספר רב של נוזקות לוורדפרס, אינן נוצרו במטרה להפיל את האתר כליל, אלא להשתמש בתשתית שלו וליצור תנועת גולשים לרכישת מוצרים באתר צד שלישי, לרוב מוצרי טיפוח ובריאות אשר אסורים לפרסום במדיה הרגילה.

קטגוריות
ווקומרס

פופאפים בווקומרס

ואמני הג'אז.

התקן את התוסף.

עדכון הלקוח בווקומרס בעמוד מוצר על פספוס הנחה מכיוון שלא רכש ממנו מספיק פריטים- הוסף את הטריגר Auto Open וטרגטינג של עמוד המוצר הרצוי והתנאים המותאמים אישית (עדכן את ה-id של המוצר וכמות הפריטים להנחה):

add_filter( 'pum_get_conditions', 'condless_pum_cart_product_quantity_conditions' );
function condless_pum_cart_product_quantity_conditions( $conditions ) {
	return array_merge( $conditions, [
		'password_page_unlocked' => [
			'group'		=> __( 'Products', 'woocommerce' ),
			'name'		=> __( 'Products', 'woocommerce' ) . ': ' . __( 'Cart', 'woocommerce' ) . ' ' . __( 'Quantity', 'woocommerce' ),
			'callback'	=> 'cart_product_quantity',
		]
	] );
}

function cart_product_quantity() {
	foreach ( WC()->cart->get_cart() as $cart_item ) {
		if ( '772' === $cart_item['product_id'] && 3 > $cart_item['quantity'] ) {
			return true;
		}
	}
	return false;
}

התראה ללקוח בווקומרס שהוא עומד לרוכש מוצר שאינו זמין במלאי כרגע (למוצרים פשוטים):

  • הפעל את האפשרויות של השורטקודים ושל הקלאסים בכפתור הוספה לסל שבתוסף
  • צור פופאפ בשם simple_is_on_backorder1 וטרגטינג של All Products
  • בתוכן הפופאפ הכנס את השורטקוד [current_add_to_cart] והתראה ללקוח על שעומד להוסיף מוצר שאינו זמין כרגע
  • במידה ומוגדר AJAX בעמוד ארכיון צור פופאפ נוסף עם טריגר Click Open על archive_is_on_backorder1. והאפשרות "do not prevent.." והכנס בתוכן הפופאפ התראה ללקוח על שהוסיף מוצר שאינו זמין כרגע, במידה ולא השתמש בקוד:
add_filter( 'woocommerce_loop_add_to_cart_args', 'condless_add_class', 10, 2 );
function condless_add_class( $args, $product ) {
	if ( $product->is_type( 'simple' ) && $product->is_on_backorder() && ! is_product() && 'no' === get_option( 'woocommerce_enable_ajax_add_to_cart' ) ) {
		$product_id = $product->get_id();
		$args['class'] .= ' popmake-archive_backorder-' . $product_id;
		$out = isset( $product->get_availability()['availability'] ) ? '<div>' . $product->get_availability()['availability'] . '</div>' . '<a href=' . $product->add_to_cart_url() . '>' . $product->add_to_cart_text() . '</a>' : '';
		echo do_shortcode( "[popup id='archive_backorder-" . $product_id . "']" . $out . "[/popup]" );
	}
	return $args;
}

כפי שבוודאי שמת לב- פסטוריוס, קרטר, ואלדס וכל שמות הקוד האחרים של גרסאות וורדפרס, הם שמות של אמני ג'אז מפורסמים, בהשראת מתכנתי הליבה של וורדפרס, אשר חולקים אהבה למוזיקת הג'אז.