Warning! WP Super Cache caching was broken but has been fixed! The script advanced-cache.php could not load wp-cache-phase1.php

  1. Troligtvis är adressen fel, ofta kan detta uppstå när man deployar wp-config via deployverktyg och det är felkonfat. Pluginet lagar sig själv om man laddar om i admin, då kan man se vilken sökväg det ska vara. Det ska alltså vara sökvägen till pluginmappen och inte cache-mappen i wp-content.
  2. The constant is not defined until after the plugin loads. This error is possible if the line ”require_once(ABSPATH . ’wp-settings.php’);” is present in wp-config.php . WPCACHEHOME is probably being defined after this line, but needs to be defined above it.
define( 'WPCACHEHOME', '<site root>/wp-content/plugins/wp-super-cache/' );
require_once(ABSPATH . 'wp-settings.php');

Debug.log

// Enable Debug logging to the /wp-content/debug.log file
define( 'WP_DEBUG_LOG', true );
function track_redirects_in_template() {
	if ( did_action( 'wp_redirect' ) ) {
		error_log( 'Redirect action triggered in template.' );
	} else {
		error_log( 'No redirect detected in template.' );
	}
}
add_action( 'template_redirect', 'track_redirects_in_template' );
function check_is_singular_essay() {
	if ( is_singular( 'my-cpt' ) ) {
		error_log( 'My CPT post is being accessed.' );
                global $post;
                error_log( 'We are on: ' . $post->ID );
	}
}
add_action( 'wp_head', 'check_is_singular_essay' );
error_log( 'Message | post type: ' . get_post_type() . ' | ' . get_the_title() );
global $wp_query;
error_log( 'Query Variables: ' . print_r( $wp_query->query_vars, true ) );
add_action( 'init', function() {
    global $wp_rewrite;
    error_log( print_r( $wp_rewrite->wp_rewrite_rules(), true ) );
} );
add_filter( 'request', function ( $query_vars ) {
    error_log( 'Request Vars During Parse: ' . print_r( $query_vars, true ) );
    return $query_vars;
} );
add_action( 'init', function () {
    $query = new WP_Query([
        'post_type' => 'my-cpt',
        'posts_per_page' => -1,
    ]);

    if ( $query->have_posts() ) {
        error_log( 'CPT found: ' . $query->posts[0]->post_title );
    } else {
        error_log( 'No cpt posts found in query.' );
    }
} );
add_action( 'init', function () {
    $query = new WP_Query([
        'post_type' => 'my-cpt',
        'posts_per_page' => -1,
    ]);

    if ( $query->have_posts() ) {
        error_log( 'CPT found: ' . $query->posts[0]->post_title );
    } else {
        error_log( 'No cpt posts found in query.' );
    }
} );
add_action( 'init', function () {
    error_log( 'Registered Post Types: ' . print_r( get_post_types(), true ) );
} );
add_action( 'template_redirect', function() {
    error_log( 'Current User Caps: ' . print_r( wp_get_current_user()->allcaps, true ) );
    error_log( 'Current User Role: ' . implode( ', ', wp_get_current_user()->roles ) );
    error_log(print_r(get_role('subscriber')->capabilities, true));
}

Töm Action Scheduler Woocommerce

Töm logs-tabellen och därefter actions:

DELETE FROM `toolwp_actionscheduler_actions` WHERE `status` = 'complete'
DELETE FROM `toolwp_actionscheduler_actions` WHERE `status` = 'canceled'
DELETE FROM `toolwp_actionscheduler_actions` WHERE `status` = 'failed'

Länka utvald bild-blocket

<?php
/**
 * Modify featured image/post thumbnail block on products
 *
 * @param string|null $block_content The pre-rendered content. Default null.
 * @param WPBlock     $block         The block being rendered.
 * @return string modified Block HTML
 */
function modify_featured_image_markup( $block_content, $block ) {
    global $post;

    if ( get_post_type( $post ) === 'product' && $block['blockName'] === 'core/post-featured-image' ) {

        $img_url = get_the_post_thumbnail_url( get_the_ID(), 'full' );

        $pattern = '/<figure(.*?)>(.*?)<img(.*?)src=["\']([^"\']+)["\'](.*?)>(.*?)<\/figure>/s';
        $replacement = '<figure$1>$2<a class="featured-image-link lightgallery-item" href="' . $img_url . '"><img$3src="$4"$5></a>$6</figure>';

        return preg_replace( $pattern, $replacement, $block_content );

    }

    return $block_content;
}

add_filter( 'render_block_core/post-featured-image', 'modify_featured_image_markup', 10, 2 );

Hur man använder wp_nonce_field()

Retrieve or display hidden nonce field for a form.

The nonce field is used to validate that the contents of the form came from the location on the current site and not somewhere else. The nonce does not offer absolute protection, but should protect against most cases. It is very important to use nonce field in forms.

The $action and $name are optional, but if you want to have better security, it is strongly suggested to set those two parameters. It is easier to just call the function without any parameters, because validation of the nonce doesn’t require any parameters, but since crackers know what the default is it won’t be difficult for them to find a way around your nonce and cause damage.

The input name will be whatever $name value you gave. The input value will be the nonce creation value.

Return

String. Nonce field HTML markup.

Usage

wp_nonce_field( $action, $name, $referer, $echo );

$action(int/string) Action name. The nonce token is generated based on it. Default: -1

$name (string) The value of the name attribute of the input HTML tag. The value of the field can be taken from $_POST[ $name ] variable. Default: ’_wpnonce’

$referer (true/false) Whether to set a referer field for validation. Hidden referer field can be added along with the nonce field. Also, such referer field can be added separately with wp_referer_field() function.
Default: true

$echo(true/false) false — don’t print, return the data to the variable for further handling. Default: true

Form data verification

<form method="post">
   <!-- some inputs here ... -->
   <?php wp_nonce_field( 'name_of_my_action', 'name_of_nonce_field' ); ?>
</form>

Output:

output: <input type="hidden" id="_wpnonce" name="_wpnonce" value="5284708911" />
<input type="hidden" name="_wp_http_referer" value="/permalink" />

After the form data has been sent, when handling the data the nonce code must be verified with wp_verify_nonce() function. Like so:

<?php
if ( empty($_POST) || ! wp_verify_nonce( $_POST['name_of_nonce_field'], 'name_of_my_action') ){
   print 'Verification failed. Try again.';
   exit;
}
else {
   // Data handling
}

If request data is received in the admin panel, it can be verified with check_admin_referer() function. If the verification has not been passed, then check_admin_referer() automatically print the error message and stop the further PHP execution — so there’s no need to specify what to do if the verification is failed.

function my_handler_function(){

	// verification
	// On failed verification, prints a error message and kills PHP execution.
	check_admin_referer( 'name_of_my_action', 'name_of_nonce_field' );

	// data handling
}

Lägg till klass och attribut på heading för att t.ex. göra en horisontell linje efter en rubrik

I JS nedan skapar vi en checkruta på headingblocken som i sin tur lägger på en klass på elementet om ibockad. Längst ner hittar vi ipmAddExtraProps där vi lägger till den inmatade texten som data-attribut på elementet. På så vis kan vi använda samma text i en ::before-deklaration. Väldigt omständigt men det är ett sätt att göra det på om man inte kan injecta <span> och grejer runt texten.

import assign from 'lodash.assign';
import { appendClassNames } from './helpers/appendClassNames';

const { createHigherOrderComponent } = wp.compose;
const { Fragment } = wp.element;
const { InspectorControls } = wp.blockEditor;
const { PanelBody, SelectControl, CheckboxControl } = wp.components;
const { addFilter } = wp.hooks;
const { __, _x } = wp.i18n;


/**
 * Add spacing control attribute to block.
 *
 * @param {object} settings Current block settings.
 * @param {string} name Name of block.
 *
 * @returns {object} Modified block settings.
 */
const addControlAttributes = (settings, name) => {

	// Do nothing if it's another block than our defined ones.
	if (name !== 'core/heading') {
		return settings;
	}

	// Use Lodash's assign to gracefully handle if attributes are undefined
	settings.attributes = assign(settings.attributes, {
		headingline: {
			type: 'boolean',
			default: false
		}
	});

	return settings;
};



/**
 * Create HOC to add spacing control to inspector controls of block.
 */
const additionalSettings = createHigherOrderComponent((BlockEdit) => {
	return (props) => {

		// Do nothing if it's another block than our defined ones.
		if (props.name !== 'core/heading') {
			return (
				<BlockEdit {...props} />
			);
		}

		const { headingline } = props.attributes;

		return (
			<Fragment>
				<BlockEdit {...props} />
				<InspectorControls>
					<PanelBody
						title={_x('Heading settings','heading line label', 'ipm-gef')}
						initialOpen={false}
					>
						<CheckboxControl
							label={_x('Line', 'heading line label', 'ipm-gef')}
							checked={ headingline }
							onChange={(selectedLineOption) => {
								props.attributes.className = appendClassNames(props.attributes.className, 'has-heading-line', headingline, selectedLineOption)
								props.setAttributes({
									headingline: selectedLineOption,
								});
							}}
						/>

					</PanelBody>
				</InspectorControls>
			</Fragment>
		);
	};
}, 'additionalSettings');

addFilter('blocks.registerBlockType', 'ipm/settings/heading-attributes', addControlAttributes);
addFilter('editor.BlockEdit', 'ipm/settings/heading-controls', additionalSettings);



function ipmAddExtraProps(extraProps, blockType, attributes) {
	if (blockType.name === 'core/heading' && attributes.headingline === true) {

		return {
			...extraProps,
			'data-heading-content': attributes.content,
		};
	}

	return extraProps;
}
addFilter('blocks.getSaveContent.extraProps', 'ipm/add-extra-props', ipmAddExtraProps);
&.has-heading-line {
		background-color: var(--color-white);
		padding-right: 1rem;
		position: relative;
		display: flex;

		&::before {
			background: var(--color-gray--darkest);
			content: "";
			display: inline-block;
			width: calc(100%);
			height: 1px;
			position: absolute;
			right: 0;
			top: 50%;
			transform: translateY(-50%);
		}

		&::after {
			content: attr(data-heading-content);
			position: absolute;
			background: #fff;
			display: block;
			padding-right: 1rem;
		}
	}

Men, det finns en stor nackdel med detta och det är att text i pseudoelement inte är markerbar.

CSS Grid to the rescue:

&.has-heading-line {
		display: grid;
		grid-template-columns: auto minmax(0, 1fr);
		align-items: center;
		grid-gap: 1rem;

		&::after {
			content: '';
			border-top: 1px solid var(--color-gray--darkest);
		}
}

Skapa ett default pattern för en custom post type med kod för hybridtema i WP

Skapa en fil som heter inc/pattern.{cpt}-template.php i ditt CPT-tillägg.

Lägg till template till dina $args när du registrerar din CPT:

'template' => array(
		array(
			'core/pattern',
			array(
				'slug' => 'erik/{cpt}-template',
			),
		),
	),

Registrera därefter en custom pattern category och ett block pattern (jag brukar lägga det rakt under register_post_type() ):

/* Register your custom category */
function erik_register_pattern_categories() {
	if ( function_exists( 'register_block_pattern_category' ) ) {
		register_block_pattern_category(
			'template',
			array( 'label' => __( 'template', 'erik-cpt'   ) )
		);
	}
}

/* Register your block Pattern */
function erik_register_patterns() {
	if ( function_exists( 'register_block_pattern' ) ) {

		ob_start();
		include( 'inc/pattern.{cpt}-template.php');
		$pattern_{cpt}_template = ob_get_clean();

		register_block_pattern(
			'erik/{cpt}-template',
			array(
				'title'       => __( '{cpt} template', 'ipm-patterns' ),
				'description' => _x( 'Template blocks setup for {cpt}.', 'Block pattern description', 'erik-cpt' ),
				'categories' => ['template'],
				'content'     => $pattern_{cpt}_template,
			)
		);
	}
}

Lägg till ditt mönster till filen pattern.{cpt}-template.php du skapade tidigare. Använd Gutenberg-redigeraren för att skapa mönstret och välj sedan Kopiera alla block från menyn (tre vertikala prickar) längst uppe till höger. Klistra sedan in detta i filen (exempel nedan). Kopiera inte över PHP-kommentarerna överst.

Glöm inte att byta ut {cpt} till namnet på din posttyp (eller valfritt).

Notera att man bara kan ha ett mönster per posttyp (vad jag vet) och om man ändrar mönstret i efterhand så kommer inte befintliga poster att uppdateras.

<?php
/**
 * Title: A block template for {cpt}
 * Slug: erik/{cpt}-template
 * Inserter: false
 */
?>

<!-- wp:columns {"style":{"spacing":{"margin":{"bottom":"var:preset|spacing|30"}}},"marginBottom":"mb\u002d\u002dx2"} -->
<div class="wp-block-columns" style="margin-bottom:var(--wp--preset--spacing--30)"><!-- wp:column {"width":"33.33%"} -->
	<div class="wp-block-column" style="flex-basis:33.33%"></div>
	<!-- /wp:column -->

	<!-- wp:column {"width":"66.66%"} -->
	<div class="wp-block-column" style="flex-basis:66.66%"><!-- wp:paragraph {"className":"is-style-default"} -->
		<p class="is-style-default">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent sit amet dapibus nibh. Mauris congue gravida velit, quis maximus leo molestie ut. Phasellus non nibh nunc. Donec efficitur leo nec tempor pulvinar. Nulla viverra pellentesque ultrices. Nam malesuada maximus facilisis. Proin felis tellus, lobortis nec pellentesque eu, sagittis non purus. Vivamus porta viverra felis, ut ornare velit. Vestibulum euismod eros lacus, eget posuere leo feugiat vel.</p>
		<!-- /wp:paragraph --></div>
	<!-- /wp:column --></div>
<!-- /wp:columns -->

<!-- wp:columns {"style":{"spacing":{"margin":{"bottom":"var:preset|spacing|30"}}}} -->
<div class="wp-block-columns" style="margin-bottom:var(--wp--preset--spacing--30)"><!-- wp:column -->
	<div class="wp-block-column"><!-- wp:image {"className":"full-width","fullWidth":true} -->
		<figure class="wp-block-image full-width"><img alt=""/></figure>
		<!-- /wp:image --></div>
	<!-- /wp:column -->

	<!-- wp:column -->
	<div class="wp-block-column"><!-- wp:image {"className":"full-width","fullWidth":true} -->
		<figure class="wp-block-image full-width"><img alt=""/></figure>
		<!-- /wp:image --></div>
	<!-- /wp:column --></div>
<!-- /wp:columns -->

<!-- wp:group {"style":{"spacing":{"margin":{"bottom":"var:preset|spacing|40"}}},"layout":{"type":"constrained"}} -->
<div class="wp-block-group" style="margin-bottom:var(--wp--preset--spacing--40)"><!-- wp:image {"className":"full-width","fullWidth":true,"marginBottom":"mb\u002d\u002dx3"} -->
	<figure class="wp-block-image full-width"><img alt=""/></figure>
	<!-- /wp:image --></div>
<!-- /wp:group -->

Om du registrerar din posttyp i en klass så kör du patternfunktionerna i construct med:

public function __construct() {			
	add_action( 'init', array($this, 'erik_register_patterns') );
	add_action( 'init', array($this, 'erik_register_pattern_categories') );
}

Alternativ för betalning på Internet (med WordPress)

Priser hämtade nov 2023

Förr i tiden kunde man enkelt hänga på en köpknapp från Paypal, a la 

https://www.paypal.com/buttons/ men jag vet inte om det är någon höjdare numera.

Om man vill utgå från ett formulär så har två av de största premium-formulärbyggarna för WordPress (något begränsade) betalningsalternativ man kan hänga på: 

Gravity Forms

Basic $59 / år

Elite $259 / år

Pro $159 / år

2Checkout (Elite), Stripe (Pro), Paypal Checkout (Pro)

Ninja Forms

Plus $99/år

Paypal ingår

Pro $199/år

Stripe, Authorize.net och Elavon ingår

Notera att Stripe erbjuder ex Klarna Checkout(vet ej hur det fungerar)

Här finns även en uppstickare som verkar intressant:

WP Simple Pay

Klarna, Stripe, Google Pay, Apple Pay etc.

Från $49.50/år men kräver troligtvis $199.50 för att få ex Klarna

Easy Digital Downloads

Ett annat alternativ som påminner om WooCommerce (och är en otroligt stor lösning om man inte har fysiska produkter, tror det är den näst största i WP-sfären efter Woo) är Easy Digital Downloads.https://easydigitaldownloads.com/

Inkluderar Stripe och PayPal

Från €95/år – antagligen krävs dyrare nivå (€192 el. €288)

Precis som med WooCommerce bygger man ut med extra tillägg beroende på önskad funktionalitet. Woo har dock väldigt många fler (och fler svenskanpassade) lösningar enligt min uppfattning.

WooCommercebaserade lösningar

WooCommerce, världens största e-handelsverktyg och byggt som ett tillägg till WordPress. Man kan lägga upp en tjänst som en produkt. Det behöver inte vara fysiska produkter man säljer men det blir dock en skillnad i köpförfarandet. Man lägger produkt i varukorg kontra ett formulär med köpinfo (jämför Gravity, Ninja, WPSP ovan).

Betaltjänster (payment gateways) för WooCommerce

Paypal ingår (tror det är https://woo.com/products/woocommerce-paypal-payments/)

Manuella alternativ så som Gratis, Betala fysiskt (alltså en form av bokning), faktura/bankgiro ingår.

Klarna, Walley, Qliro, Worldline (tidigare Bambora), Svea m.fl. erbjuder färdiga gratis tillägg för att koppla ihop med WooCommerce. Jag tror att alla (osäker på Svea) innehåller bl.a. Swish som betalmetod.

Swish (för) handel

Redlight Media i Malmö erbjuder ett tillägg till WooCommerce för enbart Swishbetalning (960 kr/år). Notera att precis som med övriga betaltjänstleverantörer så tillkommer Swish egna kostnad. Kostnaderna skiljer sig åt beroende på ett antal faktorer som ex bank. Men ett prisexempel (lånat från Angry Creative så vet inte hur aktuellt det är 2023/2024) kan se ut så här, för att få en uppfattning:

WooCommerce: gratis

Swishtiullägg till WC: 960 kr/år

Uppläggningsavgift Swish: 1000 kr

Månads- eller årsavgift: ca 50 kr/mån alt. 500-1500 kr/år beroende på bank

Transaktionsavgift: 1-3 kr

Ungefärliga prisjämförelser

TjästKostnad
WooCommerce + Klarna, Walley, Qliro, Worldline etcGratis tillägg, betala för respektive tjänst (gissningsvis månadsavgift + transaktionsavgift)
WooCommerce + Swish Handel960 kr / år för swishtillägget + avtal med Swish (månadsavgift + transaktionsavgift)
Easy Digigtal DownloadsGissningsvis €192 / år + avtal med ex Klarna (månadsavgift + transaktionsavgift)
WP Simple PayGissningsvis $199,50 / år + avtal med ex Klarna (månadsavgift + transaktionsavgift)
Ninja FormsFrån $99/år (om Paypal funkar) men antagligen $199 / år + avtal med ex Stripe (transaktionsavgift + procentuell avgift – helt beroende på Stripelösning och om man ex har Klarna därigenom)
Gravity Forms$159 / år, då ingår PayPal Checkout eller Stripe. Tillkommer transaktionsavgift + procentuell avgift – helt beroende på Stripelösning och om man ex har Klarna därigenom

Jag tror att man tänka att det kostar som minst ~ 2 000 kr / år oavsett tjänst man väljer. Exklusive att jag rekommenderar att hålla sajt och tillägg ajour (gärna 3-4 gånger per år) för att undvika säkerhetshål, att något går sönder eller för den delen få nya features. Samt att det totalt tenderar att gå mindre tid vid mindre insatser ofta, än om man skulle göra en stor uppdatering vid färre tillfällen (1 gång/år eller mer sällan).

Prisexempel från Klarna är ruggigt svårt att hitta men jag har exempelpriser nedan men osäker hur gamla dessa är:

Fast avgift per transaktion: 3,50 SEK

Rörlig avgift på transaktionsvärde: 2.79%

Säljer man en produkt för 1 000 kr på ett år skulle det då innebära minst 2 000 kr för att använda tjänsterna samt strax över 30 kr i transaktionsavgifter (Klarna).

Byt ut admin bar logo-länk

add_action( 'wp_before_admin_bar_render', 'change_admin_logo_link' );
 
function change_admin_logo_link() {
     
    global $wp_admin_bar;
     
    // Get the logo node
    $menu_node = $wp_admin_bar->get_node('wp-logo');
 
    // Change the link to wp-admin
    $menu_node->href = network_admin_url();
 
    // Add the modified node back
    $wp_admin_bar->add_node( $menu_node );
 
    // Clean up
    unset( $menu_node );
}

Lista WooCommerce produktetiketter som ”knapplänkar” (inkl. rubrik, desc, img) på WooCommerce shopsida

Kan läggas i archive eller liknande mall

<?php 
	$page_id = get_queried_object_id();
	
	$terms = get_terms( array('product_tag') );

	if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){ ?>
		<div class="editorial-wide spacing-top-x1">
			<h2 class="epsilon"><?php _e('Choose system', 'textdomain'); ?></h2>
			<div class="tag-button-group">
				<?php foreach ( $terms as $term ) {
					$show_term = get_field('show_on_product_archive', $term);
					
					if ($term->count > 0 && $show_term === true) {
					
						if ($term->term_id == $page_id) {
							$btn_classes = 'btn btn--content active current-menu-item';
						} else {
							$btn_classes = 'btn btn--content';
						}
						
						?>
							<button class="<?php echo $btn_classes ?>" href="<?php echo get_term_link($term->term_id); ?>">
								<div class="btn--content__image">
									<?php
										$image = get_field('tag_thumbnail', $term->taxonomy . '_' . $term->term_id);
										$size = 'thumbnail'; // (thumbnail, medium, large, full or custom size)
										if ( $image ) {
											echo wp_get_attachment_image( $image['ID'], $size );
										}
									?>
								</div>
								<div class="btn--content__text">
									<span class="btn--content__title"><?php echo $term->name; ?></span>
									<span class="btn--content__desc">
										<?php 
										$custom_desc = get_field('custom_description', $term->taxonomy . '_' . $term->term_id);
										if (!empty($custom_desc)) :
											echo $custom_desc;
										else :
											echo $term->description;
										endif;
										?>
									</span>
								</div>
							</button>
						<?php
						
					}
				} ?>
			</div><!-- .tag-button-group -->	
		</div><!-- .width -->
	<?php }
	

?>

Lägga till wp user via SQL query

ADDING AN ADMIN USER TO THE WORDPRESS DATABASE USING A SQL QUERY

INSERT INTO `databasename`.`wp_users` (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES ('3', 'demo', MD5('demo'), 'Your Name', 'test@example.com', 'http://www.example.com/', '2022-09-01 00:00:00', '', '0', 'Your Name');

INSERT INTO `databasename`.`wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, '3', '[tableprefix]_wp_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}');

INSERT INTO `databasename`.`wp_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) VALUES (NULL, '3', '[tableprefix]_wp_user_level', '10');

https://stackoverflow.com/questions/13094601/changing-a-wordpress-user-to-an-admin

Lista WooCommerce produktetiketter som knapplänkar

<?php 
    $page_id = get_queried_object_id();
    
    $terms = get_terms( 'product_tag' );
    $term_array = array();
    if ( ! empty( $terms ) && ! is_wp_error( $terms ) ){
        foreach ( $terms as $term ) {
            if ($term->count > 0) {
                $term_array[$term->name] = $term->name;

                if ($term->term_id == $page_id) :
                    $btn_classes = 'btn btn--small btn--primary active current-menu-item';
                else :
                    $btn_classes = 'btn btn--small btn--secondary';
                endif;

                echo '<a class="' . $btn_classes . '" href="'.get_term_link($term->term_id).'">'.$term->name.'</a>';
            }
        }
    }
?>

Redirect entire website except WordPress Admin

<?php
if ( ! is_admin() ) {
    wp_redirect( 'https://www.mynewwebsite.com' . $_SERVER['REQUEST_URI'], 301 );
    exit;
}
<IfModule mod_rewrite.c>
RewriteEngine on RewriteCond %{REQUEST_URI} !^/wp-admin.* 
RewriteEngine on RewriteCond %{REQUEST_URI} !^/wp-login.* 
RewriteRule ^(.*)$ https://example.com$1 [R=301, L] 
</IfModule>

WordPress security

https://codex.wordpress.org/Hardening_WordPress
https://codex.wordpress.org/WordPress_Housekeeping

Automatiska uppdateringar

Auto-uppdatera WordPress core, lägg detta i wp-config.php:

define( 'WP_AUTO_UPDATE_CORE', true );

Plugins:

add_filter( 'auto_update_plugin', '__return_true' );

Teman:

add_filter( 'auto_update_theme', '__return_true' );

Ta bort plugin och theme editor

define( 'DISALLOW_FILE_EDIT', true );

Säkerhetspluggar/malware-scanners

https://wordpress.org/plugins/sucuri-scanner/
https://wordpress.org/plugins/better-wp-security/
https://secupress.me/

Two-factor Auth

https://wordpress.org/plugins/google-authenticator/
https://wordpress.org/plugins/two-factor-authentication/
https://wordpress.org/plugins/wpclef/
https://wordpress.org/plugins/rublon/screenshots/

Limit login attempts

https://wordpress.org/plugins/login-lockdown/
https://wordpress.org/plugins/login-security-solution/

Flytta wp-login

https://wordpress.org/plugins/sf-move-login/
https://wordpress.org/plugins/rename-wp-login/
https://wordpress.org/plugins/hide-login/
https://wordpress.org/plugins/lockdown-wp-admin/

Loggar

https://wordpress.org/plugins/audit-trail/
https://wordpress.org/plugins/simple-login-log/

Backup-lösningar

https://wordpress.org/plugins/wordpress-backup-to-dropbox/
https://wordpress.org/plugins/updraftplus/
https://vaultpress.com/
https://ithemes.com/purchase/backupbuddy/

Deny wp-config

order allow,deny
deny from all

Göm login-fel

add_filter('login_errors',create_function('$a', "return null;"));

File permissions

Mappar 755 eller 750
Filer 644 eller 640
wp-config.php 600

Ta bort error-reporting

wp-config:

error_reporting(0);
@ini_set(‘display_errors’, 0);

Allow/deny på IP

order deny,allow
allow from 192.168.5.1
allow from 123.456.7.8
deny from all
order allow,deny
deny from 456.123.8.9
allow from all

Övrig läsning

https://premium.wpmudev.org/blog/creating-a-disaster-recovery-plan-for-your-wordpress-site/

Lås sajt bakom inloggning

I setupen/init i functions.php

// Require login
if (!is_admin() && !is_login_page()) {
	add_action( 'init', 'check_login', 0 );
}

I functions.php

/*
 * Login check and redirect to login page
 * 
 */
function check_login() {
	// If user not logged in and not login page showing
	// show the login page for the extranet
	if (!is_user_logged_in() && !is_login_page()) {
		require 'login.php';
		exit;
	}
}

// Function to check if page showing is login page
function is_login_page() {
   return in_array($GLOBALS['pagenow'], array('wp-login.php'));
}

I login.php

// User is not logged in
	$args = array(
		'echo'           => true,
		'remember'       => true,
		'redirect'       => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
		'form_id'        => 'loginform',
		'id_username'    => 'user_login',
		'id_password'    => 'user_pass',
		'id_remember'    => 'rememberme',
		'id_submit'      => 'wp-submit',
		'label_username' => __( 'Username' ),
		'label_password' => __( 'Password' ),
		'label_remember' => __( 'Remember Me' ),
		'label_log_in'   => __( 'Log In' ),
		'value_username' => '',
		'value_remember' => false
	);
	wp_login_form( $args );
	?>
	<div class="lost-password">
		<a href="<?php echo wp_lostpassword_url( get_permalink() ); ?>" title="Glömt lösenord"<Glömt lösenord?</a><br /><br />
		<a href="<?php echo wp_registration_url();>"<Registera dig</a>
	</div><!-- .lost-password -->

Sätt klasser på fejkade ancestors i nav-menu

// Add ancestor-classes to nav menu when on single posts
add_filter( 'nav_menu_css_class', 'custom_menu_classes', 10, 2 );
function custom_menu_classes( $classes , $item ){
	if ( get_post_type() == 'case' ) {
		// remove unwanted classes if found
		
		$classes = str_replace( 'current-page-ancestor', '', $classes );
		
		// find the id you want and add the class you want
		if ( $item->object_id == 10 ) {
			$classes[] = 'current-page-ancestor current-menu-ancestor';
		}
	}
	return $classes;
}

 

ACF Flexible fields boilerplate

Fungerar utmärkt att köra som include på de sidor som behöver stöd för flexible fields

<?php
/*
 * Flexible content, ACF fields on posts/pages
 *
 * @package WordPress
 * @subpackage xxx
 */
 
$counters = array();
 
function flexible_content() {
	// Check if the flexible content field has rows of data
	if( have_rows('flexible_fields') ):
		$field_count = 0;
		// Loop through the rows of data
		while ( have_rows('flexible_fields') ) : the_row();
			
			// Update layout counter
			$layout = get_row_layout();
			
			if( !isset( $counters[ $layout ] ) ) {
				// Initialize counter
				$counters[ $layout ] = 1;
			}
			else {
				// Increase existing counter
				$counters[ $layout ]++;
			}
			$layout_class = $layout . '-' . $counters[ $layout ];
			
			
			if ( get_row_layout() == 'first_layout' ):
			/*
			 *	1st field
			 *	------------------------------------------------------------------
			 *
			*/
				// Outputs layout name and number
				echo $layout_class;
				// Outputs total count of layouts
				echo 'section-' . $field_count;
				
				
				$subfield = get_sub_field('subfield_name');
				
				
				// Example of repeater field inside flexible fields
				// check if the repeater field has rows of data
				if( have_rows('grid_block_repeater') ):
					
					// loop through the rows of data
				    while ( have_rows('grid_block_repeater') ) : the_row();	
						// Output
				    endwhile;
				    
				else :
				    // no rows found
				endif;
				
			
			elseif( get_row_layout() == 'second_layout' ) :
			/*
			 *	2nd field
			 *	------------------------------------------------------------------
			 *
			*/	
				
			
			endif;
			
			$field_count++;
		endwhile;

	else :
	// no layouts found
	endif;
}

 

Responsive oEmbeds i WP

Släng in detta i functions.php för att wrappa alla oEmbeds i embed-container. Kompletteras med lite CSS.

// Wrap oEmbeds with an embed-conatiner to make it responsive
function responsive_video_wrapping($html, $url, $attr) {
	$html = '<div class="embed-container">' . $html . '</div>';
	return $html;
}
add_filter( 'embed_oembed_html', 'responsive_video_wrapping', 10, 3);
/* Responsive embed */
.embed-container { position: relative; padding-bottom: 56.25%; /*padding-top: 30px;*/ height: 0; overflow: hidden; max-width: 100%; height: auto; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }