Categorieën
Geen categorie WooCommerce WordPress

WordPress Shopp (nl) plugin

Onlangs kwam ik een WordPress website met de Shopp webwinkel plugin tegen met daarop ook de “Tussendoor Shopp 1.2.* NL / Dutch plugin“. Aangezien ik zelf ook een aantal vertaal plugins in beheer heb was ik wel benieuwd naar de opzet van deze plugin. Na het doorbladeren van de code kwam ik er snel echter dat het ging om een aangepaste versie van de WooCommerce (nl) en/of Gravity Forms (nl) plugin.

Tussendoor heeft helaas niet even de moeite genomen om Pronamic hiervan op de hoogte te brengen. Ik ben niet helemaal bekend met de regels die beschreven in de GPL licentie, maar even vermelden dat de plugin op onze plugins is gebaseerd zou ik wel gewaardeerd hebben.

The work must carry prominent notices stating that you modified it, and giving a relevant date.

Ik heb Tussendoor nog even via Twitter gewezen op de ontbrekende credits, maar daar is helaas niet op gereageerd.

Ik weet dat onze Duitse buren ook een variant op de WooCommerce (nl) plugin hebben gemaakt, namelijk de WooCommerce (de) plugin. Deze ontwikkelaar geeft ons echter alle credits voor ons werk:

Danksagung und Copyright: Dieses Plugin ist ein Fork des hervorragenden “WooCommerce (nl)” Plugins von Pronamic, NL bzw. Remco Tolsma @pronamic. Es ist quasi die Deutsche Version davon. Es steht genauso wie die ursprüngliche Code-Basis unter GPLv2-Lizenz (oder höher). — Ein grosses Dankeschön an Pronamic, die den Weg geebnet haben! 😉

Het is jammer om te zien dat onze concullega’s uit Friesland onze code zonder vermelding gebruiken. Het gaat hier natuurlijk niet om de meeste spannende plugin, maar ik dacht wel wat Tussendoor kan kunnen wij beter. Daarom hebben we recent de Shopp (nl) plugin gelanceerd. Deze plugin is inmiddels uitgerust met de vertaling voor de volgende Shopp versies:

  • 1.2
  • 1.2.2
  • 1.2.3

We hebben al veel vertalingen verbeterd, maar waarschijnlijk zijn er nog steeds veel verbeteringen mogelijk. Heb je zelf suggesties voor betere vertalingen dan horen we het graag. Mocht je geïnteresseerd zijn in een WordPress webwinkel met Shopp, WooCommerce, WP e-Commerce, WooCommerce, eShop of een andere WordPress webwinkel plugin dan kun je uiteraard ook altijd vrijblijvend een offerte aanvragen.

Categorieën
WordPress

Van WordPress SVN naar Git

Afgelopen maanden zijn we bij Pronamic steeds actiever bezig met het inzetten van Git en GitHub. We werkten voorheen voornamelijk met Subversion, maar we merkten dat Git(Hub) steeds populairder aan het worden. Daarom vonden we het hoog tijd om ook eens te experimenteren met GitHub.

Inmiddels zijn we een aantal maanden verder en hebben we al veel geleerd over Git(Hub). Zo hebben we inmiddels een aantal nieuwe WordPress plugins onder gebracht in GitHub. Deze kunnen we inmiddels behulp van eenvoudig deploy script eenvoudig publiceren in de WordPress plugin repostiory.

Vandaag hebben we bekeken hoe we ook de ontwikkeling van onze bestaande WordPress plugins kunnen verplaatsen naar Git. Via een eenvoudig Google zoekopdracht kwamen al snel een help pagina van GitHub tegen. Hierin wordt verwezen naar de svn2git tool van Kevin Menard.

Aangezien ik nog maar sinds kort een Mac gebruiker ben was het even uitzoeken hoe we deze tool konden installeren. Uiteindelijk heb ik via MacPorts Git bijgewerkt naar de laatste versie en via gem de svn2git tool geïnstalleerd.

sudo gem install svn2git

Vervolgens kan met de volgende commando bijvoorbeeld de WooCommerce (nl) plugin verplaatsen naar Git:

svn2git http://plugins.svn.wordpress.org/woocommerce-nl/ --verbose --no-minimize-url --revision 466358

Het revisie nummer is eenvoudig te achterhalen via de WordPress Trac revisie logboek pagina: http://plugins.trac.wordpress.org/log/woocommerce-nl/. Vervolgens konden we met behulp van de volgende commando’s alles doorplaatsen naar GitHub.

git remote add origin https://github.com/pronamic/wp-woocommerce-nl.git
git push origin master
git push --all
git push --tags

Voor meer informatie over SVN en Git zie ook:

Categorieën
CSS E-commerce WooCommerce WordPress

WooCommerce wijzigt CSS selectors

Om de vormgeving van de producten op WooCommerce product archief pagina’s aan te passen maakte WooCommerce in versie 1.5.5 (of lager) altijd gebruik van de volgende CSS selector:

ul.products li {

}

Dit is ook terug te vinden in het WooCommerce less bestand waarin de standaard opmaak staat gedefinieerd:

http://plugins.trac.wordpress.org/browser/woocommerce/tags/1.5.5/assets/css/woocommerce.less#L392

We gebruikten vaak een sterkere CSS selector om de opmaak van producten op archief pagina’s aan te passen:

body ul.products li {

}

Vanaf WooCommerce 1.5.6 wordt er echter standaard een nieuwe CSS selector gebruikt. Deze selector is sterker als de door ons toegevoegde CSS selector, waardoor eventuele aanpassingen na een update niet altijd meer zichtbaar zijn.

ul.products li.product {

}

http://plugins.trac.wordpress.org/browser/woocommerce/tags/1.5.6/assets/css/woocommerce.less#L393

Dit probleem is uiteraard eenvoudig op te lossen door de eigen gedefinieerde selector ook weer specifieker te maken:

body ul.products li.product {

}

Het is echter wel de vraag in hoeverre het verstandig is om kleine aanpassingen aan het standaard meegeleverde WooCommerce thema op deze manier te realiseren. In hoeverre zijn de WooCommerce ontwikkelaars zich bewust van de gevolgen van dergelijke wijzigingen? En in hoeverre moeten de WooCommerce ontwikkelaars rekening houden met dergelijke zaken?

Categorieën
PHP WordPress

Gravity Forms conditionele omleiding

Gravity Forms is een erg krachtige formulieren plugin voor WordPress. Onlangs hebben we deze plugin gebruikt voor het opzetten van een keuzerondjes vragen test. De bezoeker moest echter afhankelijk van aantal gekozen A, B en C antwoorden doorgestuurd worden naar een specifieke pagina. Standaard kan dit niet binnen Gravity Forms geconfigureerd worden, maar met behulp van een eenvoudig filter functie kan dit wel gerealiseerd worden:

function prefix_test_confirmation($confirmation, $form, $lead, $ajax) {
	if($form['id'] == '1') {
		foreach($form['fields'] as $field) {
			$values[] = $lead[$field['id']];
		}

		$result = array_count_values($values);
		arsort($result);
		$result = key($result);

		switch($result) {
			case 'A':
				$confirmation = array('redirect' => 'http://domeinnaam.nl/test/a-antwoorden/');
				break;
			case 'B':
				$confirmation = array('redirect' => 'http://domeinnaam.nl/test/b-antwoorden/');
				break;
			case 'C':
				$confirmation = array('redirect' => 'http://domeinnaam.nl/test/c-antwoorden/');
				break;
		}
	}

	return $confirmation;
}

add_filter('gform_confirmation', 'prefix_test_confirmation', 10, 4);

Bovenstaande functie telt hoeveel dezelfde antwoorden er zijn gegevens. Dit resulteert in een data array waarbij per antwoord staat hoe vaak deze is gegeven. Vervolgens wordt met behulp van de volgende regels code het meest gegeven antwoord bepaalt:

$result = array_count_values($values);
arsort($result);
$result = key($result);

FatBat geeft deze oplossing op de PHP documentatie website:

Needed to get the index of the max/highest value in an assoc array.
max() only returned the value, no index, so I did this instead.

reset($x);   // optional. 
arsort($x); 
$key_of_max = key($x);   // returns the index.

Mocht je ook een test / enquete willen opzetten in WordPress dan kan Gravity Forms een zeer handige oplossing zijn. Mocht je hier meer informatie over willen dan kun je altijd vrijblijvende contact opnemen met Pronamic.

Categorieën
SQL WordPress

WordPress Broken Link Checker en comment_author_url

Op een grote WordPress website waarbij we veel reacties geautomatiseerd hebben geïmporteerd gaf de Broken Link Checker plugin bij veel reacties aan dat er verbroken links aanwezig waren. Al snel bleek dat deze reacties zonder URL schema (http://, ftp://, etc.) in het systeem stonden. Hierdoor kon de Broken Link Checker plugin de URL’s niet correct transformeren naar volledige URL’s.

Een ‘comment_author_url’ die als ‘www.website.nl’ in de database stonden transformeerde de Broken Link Checker plugin naar ‘http://wordpress-website.nl/2012/06/nieuwsbericht/comment-page-1/www.website.nl’. In vrijwel alle gevallen resulteert dit in een link die resulteert in een 404. Gelukkig hebben we dit probleem eenvoudig kunnen verhelpen door de ‘comment_author_url’ in de database te corrigeren.

Met behulp van de volgende database query kunnen eenvoudig de URL’s die zonder ‘http://’ beginnen opgevraagd worden:

SELECT
	*
FROM
	wp_comments
WHERE
	comment_author_url != ''
		AND
	comment_author_url NOT LIKE 'http://%'

Vervolgens kunnen deze onvolledige URL’s eenvoudig aangevuld worden met ‘http://’ met behulp van de volgende query:

UPDATE
	wp_comments
SET 
	comment_author_url = CONCAT('http://', comment_author_url)
WHERE
	comment_author_url != ''
		AND
	comment_author_url NOT LIKE 'http://%'

Mocht je ook hulp nodig hebben met het omzetten van een maatwerk website naar een krachtige WordPress website dan kun je altijd eens contact opnemen met Pronamic. We hebben veel ervaring met het geautomatiseerd importeren van berichten, pagina en reacties naar een WordPress website.

Categorieën
PHP WooCommerce WordPress

WooCommerce betaalmethode toevoegen aan e-mail

Onlangs kreeg ik van een opdrachtgever de vraag of de door de klant gekozen betaalmethode ook weergegeven zou kunnen worden in de WooCommerce e-mail. Dit zodat de administratie eenvoudiger de betaling kan controleren en de bestelling kan afronden.

Na het doorbladeren van de WooCommerce e-mail sjablonen kwam ik al snel een aantal acties tegen waarop we kunnen inhaken. In de WooComemrce ‘admin-new-order.php‘ e-mail sjabloon kan de ‘woocommerce_email_after_order_table’ actie gebruikt worden om de e-mail uit te breiden met aanvullende informatie.

function prefix_woocommerce_email_display_payment_method( $order, $is_admin_email ) {
	if ( $is_admin_email ) {
		echo '<p>';
		echo '	<strong>' , __('Payment Method:', 'text-domain') , '</strong> ';
		echo '	' , $order->payment_method_title;
		echo '</p>';
	}
}

add_action( 'woocommerce_email_after_order_table', 'prefix_woocommerce_email_display_payment_method', 10, 2 );

Mocht je hulp nodig hebben bij het opzetten van WordPress webwinkel dan kun je altijd eens contact opnemen met Pronamic.

Categorieën
SQL WordPress

WordPress berichten importeren MySQL join over 2 databases

Bij Pronamic zijn we afgelopen maanden druk bezig geweest met het omzetten van een grote maatwerk website naar WordPress. Hierbij hadden we ook de opdracht om alle bestaande berichten, foto’s, video’s, evenementen, etc. te importeren naar WordPress.

Het importeren van deze content naar WordPress realiseren we door de oude database in te lezen met PHP en de berichten in WordPress te plaatsen. Aangezien het om duizenden berichten gaat doen we het importeren in fases. We houden daarom in de oude database per item bij wat geïmporteerd is en wat fout ging. Hiervoor hebben een tweetal BOOLEAN kolommen toegevoegd aan een aantal tabellen.

ALTER TABLE content ADD wordpress_imported BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE content ADD wordpress_failed BOOLEAN NOT NULL DEFAULT FALSE;

ALTER TABLE media ADD wordpress_imported BOOLEAN NOT NULL DEFAULT FALSE;
ALTER TABLE media ADD wordpress_failed BOOLEAN NOT NULL DEFAULT FALSE;

Omdat de oude website nog steeds live staat en er nog dagelijks nieuwe berichten worden geplaatst ontvangen we regelmatig een nieuwe database dump. In deze nieuwe datadump zijn echter niet bovenstaande kolommen met data opgenomen. Om te voorkomen dat we oude berichten voor een tweede keer importeren moeten we deze kolommen dus weer toevoegen aan de nieuwe data.

Gelukkig kun je met MySQL eenvoudig in een query meerdere databases raadplegen en dus op deze manier gegevens uit meerdere databases synchroniseren. Allereerst zorgen we er voor dat we bovenstaande queries uitvoeren en vervolgens synchroniseren we de data met behulp van de volgende query:

UPDATE
	database_2.media AS targetTable
		INNER JOIN
	database_1.media AS sourceTable
			ON sourceTable.id = targetTable.id
SET
	targetTable.wordpress_imported = sourceTable.wordpress_imported ,
	targetTable.wordpress_failed = sourceTable.wordpress_failed
;

UPDATE
	database_2.content AS targetTable
		INNER JOIN
	database_1.content AS sourceTable
			ON sourceTable.id= targetTable.id
SET
	targetTable.wordpress_imported = sourceTable.wordpress_imported ,
	targetTable.wordpress_failed = sourceTable.wordpress_failed
;

Stackoverflow: http://stackoverflow.com/questions/1675333/php-mysql-joins-across-databases

We hebben bij Pronamic inmiddels vrij veel ervaring met het omzetten van zeer grote maatwerk websites naar WordPress. Mocht je ook een grote maatwerk website willen omzetten naar WordPress dan kunnen we helpen met het overzetten van de bestaande content.

Categorieën
PHP WordPress

WordPress update gebruikers met WordPress profiel bericht

Bij het ontwikkelen van een intranet oplossing met WordPress hebben we WordPress gebruikers gekoppeld aan een WordPress profiel berichten. Voor elke WordPress gebruiker die wordt aangemaakt wordt er ook automatisch een WordPress profiel bericht aangemaakt. Op deze manier hebben we met behulp van WordPress bericht archieven eenvoudig een overzicht van alle gebruikers (profielen) kunnen aanmaken. Daarnaast hebben we met krachtige WP_Query parameters een aantal handige zoek- en filter functies kunnen realiseren.

Eventueel zou een dergelijke opzet ook met een WP_User_Query object gerealiseerd kunnen worden, maar uiteindelijk liepen we hierbij tegen meer maatwerk code aan. Daarnaast konden we door te werken met WordPress profiel berichten eenvoudig gebruik van taxonomieën en uitgelichte afbeeldingen. We realiseren ons dat taxonomieën ook inzetbaar zijn voor WordPress gebruikers, maar toch liepen we daarmee ook tegen lastige problemen aan. Nadat we uiteindelijk alle functionaliteiten netjes aan elkaar geknoopt hadden liep onze opdracht echter tegen een klein probleem aan.

Het importeren van honderden intranet gebruikers leverden problemen op. De uitgelichte afbeeldingen kon niet geautomatiseerd geplaatst worden en termen werden niet gekoppeld aan de WordPress profiel berichten van een gebruiker. Wij kregen daarom de opdracht om eenmalig het één en andere te corrigeren. Onze opdrachtgever was er in geslaagd om alle data te importeren, maar het stond alleen nog niet op de juiste plek. De profiel afbeelding link stond zo opgeslagen in het Hyves veld bij een gebruiker en de afdeling term ID in het Flickr veld.

We hebben met eenvoudige WordPress maatwerk pagina sjabloon een eenvoudig script ontwikkeld die het één en andere geautomatiseerd gecorrigeerd heeft. Hieronder is dit scrip te zien, wellicht dat andere WordPress ontwikkelaars hier in de toekomst nog wat aan hebben.

<?php
/**
 * Template Name: Users update
 */

require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';

get_header(); ?>

<div id="content" role="main">
	<div class="container">
		<?php if(have_posts()) while(have_posts()): the_post(); ?>

		<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
			<header>
				<h2 class="entry-title"><?php the_title(); ?></h2>
			</header>

			<div class="entry-content">
				<?php the_content(); ?>

				<?php wp_link_pages(array('before' => '<div class="page-link">' . __('Pages:', 'eisma'), 'after' => '</div>')); ?>
			</div>
		</div>

		<?php endwhile; ?>

		<?php

		$wp_user_search  = new WP_User_Query(array(
			/*'role' => 'subscriber', */
			'fields' => 'all_with_meta' ,
			// 'number' => 1 ,
		));

		$users = $wp_user_search->get_results();

		$i = 1; 

		?>
		<table>
			<thead>
				<tr>
					<th scope="col">#</th>
					<th scope="col">Name</th>
					<th scope="col">Profile</th>
					<th scope="col">Location</th>
					<th scope="col">Business</th>
					<th scope="col">Image</th>
				</tr>
			</thead>

			<tbody>

				<?php foreach($users as $user): ?>

				<tr>
					<td>
						<?php echo $i++; ?>
					</td>
					<td>
						<?php echo $user->display_name; ?>
					</td>
					<td>
						<?php 

						$postId = get_user_meta($user->ID, 'profile_post_id', true);

						?>
						<a href="<?php echo get_permalink($postId); ?>">
							Profile
						</a>
					</td>
					<td>

						<?php 

						// locatie in flickr-veld
						$locationTermId = get_user_meta($user->ID, 'flickr', true); 

						echo $locationTermId;

						if(!empty($locationTermId)) {
							$term = get_term($locationTermId, 'location');

							if(!is_wp_error($term) && !empty($term)) {
								echo ' - ';
								echo $term->name;

								wp_set_post_terms($postId, array($term->term_id), 'location');

								delete_user_meta($user->ID, 'flickr');
							}
						}

						?>
					</td>
					<td>

						<?php 

						// bedrijfsonderdeel in youtube-veld
						$companyTermId = get_user_meta($user->ID, 'youtube', true);

						echo $companyTermId;

						if(!empty($companyTermId)) {
							$term = get_term($companyTermId, 'company');

							if(!is_wp_error($term) && !empty($term)) {
								echo ' - ';
								echo $term->name;

								wp_set_post_terms($postId, array($term->term_id), 'company');

								delete_user_meta($user->ID, 'youtube');
							}
						}

						?>
					</td>
					<td>
						<?php

						$imageUrl = get_user_meta($user->ID, 'hyves', true);

						if(!empty($imageUrl)): ?>

						<img src="<?php echo $imageUrl; ?>" width="256" alt="" />

						<?php

						$result = download_url($imageUrl);

						if(!is_wp_error($result)) {
							$date = new DateTime();

							$name = basename($imageUrl);

							$bits = file_get_contents($result);

							$result = wp_upload_bits($name, null, $bits, $date->format('Y/m'));

							if($result['error'] === false) { // no error
								$fileType = wp_check_filetype($result['file']);

								$attachment = array(
									'post_title' => get_the_title($postId) ,
									'post_mime_type' => $fileType['type'] ,
									'guid' => $result['url'] ,
									'post_parent' => $postId ,
									'post_date' => $date->format('Y-m-d H:i:s') ,
									'post_date_gmt' => get_gmt_from_date($date->format('Y-m-d H:i:s'))
								);

								$attachmentId = wp_insert_attachment($attachment, $result['file'], $postId);

								update_post_meta($postId, '_thumbnail_id', $attachmentId);

								$metaData = wp_generate_attachment_metadata($attachmentId, $result['file']);

								$updated = wp_update_attachment_metadata($attachmentId, $metaData);

								delete_user_meta($user->ID, 'hyves');
							}
						}

						endif; ?>
					</td>
				</tr>

				<?php endforeach; ?>

			</tbody>
		</table>
	</div>
</div>

<?php get_sidebar(); ?>
<?php get_footer(); ?>

Mocht je zelf ook geïnteresseerd zijn in een WordPress intranet dan kun je altijd bij Pronamic informeren naar de mogelijkheden.

Categorieën
iDEAL WordPress

WordPress iDEAL plugin

Het is alweer bijna een jaar geleden dat we bij Pronamic begonnen met de ontwikkeling van de WordPress iDEAL plugin. Inmiddels begint de plugin steeds meer vorm te krijgen en ontdekken steeds meer WordPress gebruikers de kracht van deze plugin. De plugin is inmiddels meer dan 3.000+ keer gedownload:

WordPress iDEAL plugin wordt gemiddeld 40 keer per dag gedownload

Doordat de plugin steeds meer wordt gebruikt wordt de plugin ook steeds beter. Bijna wekelijks verbeteren en optimaliseren we functionaliteiten. Ook zorgen we er voor dat de WordPress iDEAL plugin steeds meer plugins uitbreid met de iDEAL betaalmethode. Zo zijn we beginnen met Gravity Forms en is deze lijst inmiddels al flink gegroeid:

One WordPress iDEAL plugin to rule them allHet idee hiervan is dat we één goede iDEAL plugin voor WordPress ontwikkelen: “One WordPress iDEAL plugin to rule them all”. Met name voor WordPress ontwikkelaars is het erg prettig dat ze gebruik kunnen maken van één stabiele iDEAL plugin. Daarnaast is het denk ik prettig dat de WordPress iDEAL plugin door een betrouwbare Nederlandse partij (Pronamic) is ontwikkeld en wordt onderhouden.

Omdat de Pronamic iDEAL plugin ontwikkelingen flink doorgaan en de plugin steeds beter en stabieler wordt hebben we de WordPress iDEAL website gelanceerd. Op deze website zullen we proberen om informatie over problemen, updates en andere iDEAL gerelateerde informatie te plaatsen. In het eerste bericht “Pronamic iDEAL versie beta-0.9.4” is in het kort te lezen wat er zoal is verbeterd in deze versie.

Categorieën
SQL WordPress

WordPress oude URL’s doorverwijzen naar nieuwe URL’s

In het bericht “WordPress oude URL’s vervangen met nieuwe URL’s” beschreef ik dat het slim is om bij het overzetten van berichten naar WordPress het handig is om de oude / originele URL ook bij het nieuwe WordPress bericht op te slaan in een extra veld. Aan de hand daarvan kun je na het overzetten eenvoudig interne links bijwerken. Daarnaast kun je ook eenvoudig een overzicht creëren van alle oude en nieuwe URL’s zodat je oude URL’s kunt doorverwijzen naar de nieuwe URL’s met een HTTP 301 redirect.

Voor het doorverwijzen van oude URL’s naar nieuwe URL’s binnen WordPress kan de Redirection plugin gebruikt worden. Als je met deze plugin werkt en bij elk WordPress bericht ook de oude URL hebt opgeslagen in een extra (meta) veld kun je met een eenvoudige database query de redirects toevoegen aan de Redirection plugin. Hieronder zie je een query waarmee dit gerealiseerd kan worden:

INSERT
	INTO wp_redirection_items (
		url ,
		group_id ,
		action_type ,
		action_code ,
		action_data ,
		match_type
	)
	SELECT
		REPLACE(meta.meta_value, 'http://www.domeinnaam.nl', '') AS url ,
		3 AS group_id ,
		'url' AS action_type ,
		'301' AS action_code ,
		post.guid AS action_data ,
		'url' AS match_type
	FROM
		wp_posts AS post
			RIGHT JOIN
		wp_postmeta AS meta
			ON
				post.ID = meta.post_id
					AND
				meta.meta_key = 'legacy_url'
			WHERE
				post.guid != '';

Let wel op dat je de meta key waarin de oude URL staat opgeslagen wijzigt naar je eigen naamgeving. Uiteraard zal ook de domeinnaam in bovenstaande query aangepast moeten worden naar je eigen domeinnaam. Ik plaats de items overigens in een specifieke daarvoor aangemaakt Redirection group, hiervoor geef ik ‘group_id’ de waarde ‘3’.

Mocht je overigens hulp nodig hebben met het overzetten van berichten, pagina’s of andere content naar WordPress dan kun je contact opnemen met Pronamic. We hebben erg veel ervaring met het overzetten van content naar WordPress. We hebben al veel grotere maatwerk websites succesvol omgezet naar WordPress.

Update 01-08-2013: