Categorieën
PHP WordPress

W3 Total Cache mobile check

Gebruikers van de “W3 Total Cache” plugin weten dat je per “User Agent Groups”, ook wel browser groepen, verschillende pagina caches kunt hanteren. Dit is erg handig voor als je WordPress website voor mobiele apparaten anders is opgebouwd dan voor desktop browsers. Met de wp_is_mobile() functie kun je dan eenvoudig je WordPress thema aanpassen voor mobiele appareten.

W3 Total Cache mobile User Agent Groups

We liepen echter tegen problemen dat de wp_is_mobile() functie check niet overeenkwam met de standaard W3 Total Cache “User Agent Groups”. Hierdoor werd soms op desktop browsers toch de mobiele versie van de website weergegeven. Daarom zijn we opzoek gegaan naar een manier om de W3 Total Cache check te gebruiken.

Na het doorzoeken van de W3 Total Cache code kwamen uit op de volgende classes en functies:

Aan de hand hiervan hebben we de volgende help functie kunnen schrijven:

if ( ! function_exists( 'is_mobile' ) ) { 
	function is_mobile() {
		$is_mobile = false;

		if ( class_exists( 'W3_Mobile' ) ) {
			$w3_mobile = new W3_Mobile();

			$group = $w3_mobile->get_group();

			$is_mobile = $group !== false;
		}

		return $is_mobile;
	}
}

 

Categorieën
E-commerce PHP WooCommerce WordPress

WooCommerce teksten wijzigen

In het bericht “WooCommerce ‘Toevoegen aan winkelwagen’ tekst wijzigen” schreef ik al hoe je een specifieke WooCommerce tekst kon wijzigen. Helaas zijn met behulp van deze oplossing niet alle WooCommerce teksten te wijzigen. Toch komt het wel eens voor dat ook andere teksten gewijzigd moet worden. Binnen bepaalde webwinkels is “Bestellen” bijvoorbeeld een betere vertaling voor  “Checkout”  in plaats van “Afrekenen”.

Met behulp van de volgende code kunnen alle WooCommerce teksten eenvoudig aangepast worden.

/**
 * Translate WooCommerce text
 *
 * @link http://codex.wordpress.org/Plugin_API/Filter_Reference/gettext
 */
function prefix_translate_woocommerce( $translated_text, $text, $domain ) {
	if ( $domain == 'woocommerce' ) {
		switch ( $text ) {
			case 'Checkout →' :
				$translated_text = 'Bestellen';
				break;
			case 'Add to Cart' :
			case 'Add to cart' :
				$translated_text = 'Bestellen';
				break;
		}
	}

	return $translated_text;
}

add_filter( 'gettext', 'prefix_translate_woocommerce', 20, 3 );
Categorieën
SQL WordPress

WordPress database prefix wijzigen

Voor het wijzigen van de WordPress database prefix zijn verschillende plugins beschikbaar. Deze plugins wijzigen echter niet altijd alle prefixes. De WordPress database prefix wordt namelijk naast in de tabel namen ook gebruikt in de ‘options’ en ‘usermeta’ tabellen. Jan Egbert tipte me daarom over de volgende SQL query:

UPDATE wp_usermeta SET meta_key = REPLACE(meta_key, 'wp_', 'nieuweprefix_') WHERE meta_key LIKE 'wp\_%';

Via een aantal andere websites kwam ik er achter dat ook de ‘options’ tabel de WordPress database prefix wordt gebruikt. Daarom zal waarschijnlijk ook de volgende query uitgevoerd moeten worden:

UPDATE wp_options SET option_name = REPLACE(option_name, 'wp_', 'nieuweprefix_') WHERE option_name LIKE 'wp\_%';

Bovenstaande queries gaat echter fout zodra de WordPress database prefix terug komt in de optie naam of de user meta key.

umeta_id user_id meta_key meta_value
1 1 wp_pronamic_wp_version 3.5

Zal na het uitvoeren van de query gewijzigd worden naar:

umeta_id user_id meta_key meta_value
1 1 nieuweprefix_pronamic_nieuweprefix_version 3.5

De “Change DB Prefix” plugin lijkt uitgerust zijn met de juiste queries:

http://plugins.trac.wordpress.org/browser/db-prefix-change/tags/1.1/db_prefix.php#L83

Meer informatie:

Categorieën
PHP WordPress

WordPress update naar 3.5 fatal error

Bij de WordPress update van 3.4.2 naar WordPress 3.5 liepen we bij een aantal websites tegen de volgende foutmelding aan:

HTTP-fout 500 (Internal Server Error): Er is een onverwachte voorwaarde gevonden toen de server het verzoek wilde uitvoeren.

Via de Apache fouten logboek zagen we de volgende foutmelding voorbij komen:

Website 1

[Fri Jan 18 09:14:18.400710 2013] [:error] [pid 17051] [client *.*.*.*:*] PHP Warning:  Missing argument 1 for get_post(), called in /public_html/wp-includes/link-template.php on line 1125 and defined in /public_html/wp-includes/post.php on line 380

[Fri Jan 18 09:17:25.937590 2013] [:error] [pid 17268] [client *.*.*.*:*] PHP Warning:  Division by zero in /public_html/wp-includes/functions.php on line 3237

[Fri Jan 18 09:17:26.019925 2013] [:error] [pid 17144] [client *.*.*.*:*] PHP Fatal error:  Call to undefined function get_current_blog_id() in /public_html/wp-includes/user.php on line 671, referer: http://domainname.tld/wp-admin/update-core.php?action=do-core-upgrade

Website 2

[Fri Jan 18 09:44:52.166372 2013] [:error] [pid 18936] [client *.*.*.*:*] PHP Warning:  Division by zero in /public_html/wp-includes/functions.php on line 3237

[Fri Jan 18 09:44:52.190437 2013] [:error] [pid 18936] [client *.*.*.*:*] PHP Fatal error:  Call to a member function register_handler() on a non-object in /public_html/wp-includes/media.php on line 944

Waardoor deze problemen werden veroorzaakt was een groot raadsel. Ook na een handmatige update van WordPress was het probleem niet opgelost. Uiteindelijk kwamen we tot de ontdekking dat er een caching techniek (XCache) actief was op de hosting omgeving.

Hierdoor werd na de WordPress 3.5 update op de hosting omgeving nog steeds gebruik gemaakt van PHP bestanden/functies uit WordPress 3.4.2. Uiteindelijk hebben we het probleem kunnen oplossen door tijdelijke XCache uit te schakelen.

Het uitschakelen van XCache kan met behulp van de volgende regels in het .htaccess bestand:

php_flag xcache.cacher Off
php_flag xcache.size 0
php_flag xcache.stat Off

Mocht je zelf ook een keer tegen onverklaarbare foutmeldingen aanlopen na een WordPress update dan is het wellicht goed om eens na te gaan welke caching technieken actief zijn.

Categorieën
PHP WordPress

WordPress menu limiet

Binnen WordPress kunnen menu’s eenvoudig aangemaakt en beheert worden. Bij grotere menu’s kunnen er echter problemen ontstaan. Menu’s worden soms niet meer goed opgeslagen of het aantal menu items is beperkt. Binnen het WordPress forum zijn hier verschillende topics over te vinden:

Dit probleem wordt veroorzaakt door de Suhosin module van PHP. Deze module beschermt servers tegen onveilig gebruik van PHP. Dit doet Suhosin onder andere door verschillende beperkingen te activeren.

Eén van de beperking is het aantal ‘post’ en ‘request’ variabelen. WordPress werkt met deze variabelen om menu’s op te slaan. Een minder handige constructie omdat je tegen limieten van bijvoorbeeld Suhosin kunt aanlopen.

Gelukkig kunnen de limieten in veel gevallen verhoogd worden. Vaak moet dit uitgevoerd worden door de hosting partij. Als je echter zelf een server beheert dan kun je dit ook eenvoudig zelf doen. Ik wil graag dat deze limieten per directory in een .htacces bestand geconfigureerd kunnen worden.

Hiervoor heb ik de volgende wijziging doorgevoerd in het “suhosin.ini” configuratie bestand:

nano /etc/php5/apache2/conf.d/suhosin.ini

Vervolgens heb ik de volgende regel gewijzigd van:

suhosin.perdir = "0"

naar:

suhosin.perdir = "pr"

De ‘p’ en ‘r’ karakters geven aan dat ‘post’ en de ‘request’ configuratie instellingen per map zijn in te stellen. Dit onderdeel van Suhosin is niet goed gedocumenteerd, maar in de broncode van de Suhosin bibliotheek is de werking hiervan eenvoudig te raadplegen.

Vervolgens kunnen we het volgende opnemen in het .htaccess bestand om groter menu’s te kunnen beheren binnen WordPress:

# BEGIN PHP
<IfModule mod_php5.c>
	php_value suhosin.post.max_vars 2048
	php_value suhosin.request.max_vars 2048
</IfModule>
# END PHP

Meer informatie:

Categorieën
WordPress

Wijzig WordPress network site domeinaam

Om een WordPress netwerk site domeinnaam te wijzigen kunnen de volgende stappen genomen worden:

  1. Maak een backup van de database.
  2. Pas de volgende query aan en voer deze uit:
    UPDATE wp_2_options SET option_value = REPLACE(option_value, 'huidige-domeinnaam.nl', 'nieuwe-domeinnaam.nl') WHERE option_value NOT LIKE '%:{%';
    UPDATE wp_2_posts SET post_content = REPLACE(post_content, 'huidige-domeinnaam.nl', 'nieuwe-domeinnaam.nl');
    UPDATE wp_2_posts SET guid = REPLACE(guid, 'huidige-domeinnaam.nl', 'nieuwe-domeinnaam.nl');
    UPDATE wp_2_postmeta SET meta_value = REPLACE(meta_value, 'huidige-domeinnaam.nl', 'nieuwe-domeinnaam.nl') WHERE meta_value NOT LIKE '%:{%';
    UPDATE wp_2_links SET link_image = REPLACE(link_image, 'huidige-domeinnaam.nl', 'nieuwe-domeinnaam.nl');

    Wijzig ‘wp_2’ naar de prefix van de network site, ‘huidge-domeinnaam.nl’ naar de huidige domeinnaam en ‘nieuwe-domeinnaam.nl’ naar de nieuwe domeinnaam.

  3. Pas de volgende rewrite regels aan en voeg deze toe aan het .htaccess bestand:
    <IfModule mod_rewrite.c>
    	RewriteEngine On
    	RewriteCond %{HTTP_HOST} ^(www\.)?huidige-domeinnaam\.nl
    	RewriteRule (.*)$ http://nieuwe-domeinnaam.nl/$1 [R=301,L]
    </IfModule>

    Wijzig ‘huidge-domeinnaam.nl’ naar de huidige domeinnaam en ‘nieuwe-domeinnaam.nl’ naar de nieuwe domeinnaam.

  4. Geef de adreswijziging door aan Google via de Google Webmaster Tools(Configuratie » Adreswijziging).

Voor meer informatie over adreswijziging van WordPress network websites, zie ook:

Categorieën
SQL WordPress

WordPress meta veld met URL zonder http://

Afgelopen maanden ben ik een aantal keer WordPress websites tegen gekomen met berichten waarbij in een meta veld een URL naar een externe website werd opgeslagen. In veel gevallen was deze URL echter niet voorzien van het http:// protocol prefix. Dit resulteerde aan de voorkant van de website in onjuiste URL’s.

Als binnen een WordPress bericht in een meta veld ‘website’ alleen ‘www.domeinnaam.tld’ stond resulteerde dit in de volgende link: http://website.tld/2012/08/wordpress-bericht/www.domeinnaam.tld/, terwijl dit eigenlijk: http://www.domeinnaam.tld/ had moeten zijn. Dit probleem is echter eenvoudig op te lossen met een database query.

Met behulp van de volgende query zijn URL’s zonder de http:// protocol prefix op te vragen:

SELECT
	*
FROM
	wp_postmeta 
WHERE
	meta_key = 'website'
		AND
	meta_value != ''
		AND
	meta_value NOT LIKE 'http%'

Als de ouput van deze query correct is dan kan met behulp van de volgende query de URL’s uitgebreid worden met het http:// protocol.

UPDATE 
	wp_postmeta 
SET 
	meta_value = CONCAT('http://', meta_value)
WHERE
	meta_key = 'website'
		AND
	meta_value != ''
		AND
	meta_value NOT LIKE 'http%'
;
Categorieën
Geen categorie PHP SQL WordPress

WordPress gebruikers niet in auteur dropdown

Bij veel geavanceerdere WordPress websites zijn de standaard WordPress gebruikersrollen en bijbehorende mogelijkheden (capabilities) niet meer voldoende. Gelukkig zijn deze gebruikersrollen eenvoudig met allerlei plugins te beheren en uit te breiden. Zo kan men bijvoorbeeld met behulp van de Members plugin dit alles via eenvoudige gebruikersinterface beheren.

Toch blijken er ook nog wel een aantal nadelen te kleven aan het inzetten van maatwerk gebruikersrollen. Zo loop ik regelmatig tegen het probleem aan dat gebruikers met maatwerk gebruikersrollen niet zichtbaar zijn de auteur dropdown. Hierdoor hebben eindbgeruikers niet de mogelijkheid om een gebruiker met maatwerk rol als auteur toe te wijzen aan een WordPress bericht.

Dit probleem wordt veroorzaakt doordat binnen de auteur meta box gebruik gemaakt wordt van de wp_dropdown_users() functie. De wp_dropdown_user() functie maakt op zijn beurt weer gebruik van get_users() en dus WP_User_Query. Met behulp van deze query klasse kunnen gebruikers opgevraagd. Met de ‘who’ parameter kan er geselecteerd worden op alle gebruikers of enkel auteurs.

Binnen de auteur meta box worden alleen de auteurs weergegeven. De implementatie van WP_User_Query vraagt de auteurs echter op aan de hand van het gebruikersniveau (level). WordPress gebruikersniveaus is een techniek die werd gebruik in WordPress versies voor 2.0. Tegenwoordig wordt bij het aanmaken van maatwerk gebruikersrollen deze gebruikersniveaus niet meer meegenomen.

In veel gevallen is het echterwel  verstandig om ook de gebruikersniveaus te koppelen aan maatwerk gebruikersrollen. Dit kan eenvoudig gerealiseerd worden door met behulp van de Members plugin respectievelijk de volgende mogelijkheden (capabilities) toe te voegen:

  • level_0
  • level_1
  • level_2
  • level_3
  • level_4
  • level_5
  • level_6
  • level_7
  • level_8
  • level_9
  • level_10

Dit zorgt ervoor dat zodra er gebruikers met een maatwerk gebruikersrol worden aangemaakt het gebruikersniveau niet op 0 blijft staan. Doordat deze niet op 0 blijft staan zullen deze gebruikers automatisch ook in de auteur dropdown weergegeven worden. Indien je al veel gebruikers met gebruikersniveau 0 in je systeem hebt staan dan kun je deze eenvoudig bijwerken met behulp van de volgende query:

UPDATE 
	wp_usermeta
SET 
	meta_value = 4
WHERE
	meta_key = 'wp_user_level'
		AND
	meta_value = 0
		AND
	user_id IN (
		SELECT 
			user_id 
		FROM (
			SELECT
				DISTINCT user_id 
			FROM 
				wp_usermeta
			WHERE 
				meta_key = 'wp_capabilities'
					AND
				meta_value LIKE '%company_author%'
		) AS temporary_table
	);

Met behulp van bovenstaande query upgrade ik gebruikers met de gebruikersrol ‘company_author’ en gebruikersniveau 0 naar gebruikersniveau 4.

Categorieën
WordPress

Plesk zero-day beveiligingslek WordPress website hack

Vorige maand berichten verschillende websites al over een zero-day beveiligingslek in Plek. Hierdoor zouden duizenden websites geïnfecteerd zijn geraakt met ongewenste zaken. Ik merk zelf dat ook veel Nederlandse de dupe zijn geworden van deze beveiligingslek. Op Security.nl is in het bericht “Hacker verkoopt zero-day voor onbekend Plesk-lek” hierover het volgende te lezen:

Onlangs rapporteerde een beveiligingsonderzoeker van Sucuri een toename van het aantal aanvallen op Plesk beheerderspanelen.

Op het Plesk-forum klagen verschillende gebruikers dat hun websites zijn gehackt, ook al gebruiken ze de laatste versie.

Meer informatie over deze beveiliginslek in Plesk:

Categorieën
PHP WordPress

WordPress eenvoudig in debug mode

Elke WordPress ontwikkelaar moet wel eens snel een probleem oplossen op een website die al live staat. Om problemen op te lossen is het vaak handig om te werken in debug mode. In een live omgeving is dit echter vaak niet een goed idee, omdat bezoekers dan onnodige meldingen te zien krijgen. Dit is echter eenvoudig te omzeilen door het volgende in het wp-config.php bestand te zetten:

define( 'WP_DEBUG', filter_input( INPUT_GET, 'debug', FILTER_VALIDATE_BOOLEAN) );

Vervolgens kun je eenvoudig de WordPress website in debug mode zetten door deze als volgt op te vragen:

  • http://domeinnaam.tld/?debug=true

Ook de volgende varianten zullen functioneren dankzij de krachtige FILTER_VALIDATE_BOOLEAN validatie filter.

  • http://domeinnaam.tld/?debug=1
  • http://domeinnaam.tld/?debug=on
  • http://domeinnaam.tld/?debug=yes

Het is waarschijnlijk wel verstandig om deze functie na het oplossen van het probleem weer te verwijderen en debug mode gewoon op ‘false’ te zetten.