Maandelijks archief: november 2010

Magento webwinkel verhuizen

Het verhuizen van een Magento webwinkel naar een nieuwe server / locatie kan een hele klus zijn. Een Magento installatie die al een aantal jaren actief kan al snel 2+ GB aan ruimte in nemen. Met meer dan 100.000+ bestanden en 25.000+ mappen kan het verhuizen veel tijd kosten. Daarnaast is er vaak ook een MySQL database die 500+ MB aan data bevat.

Op de Wiki van Magento staat beschreven hoe je een Magento installatie kunt verhuizen naar een andere locatie. In eerste instantie wordt beschreven dat je een nieuwe Magento installatie moet opzetten en vervolgens de oude data moet importeren. Aan het eind van het artikel wordt echter ook een alternatieve methode toegelicht. In de alternatieve variant hoef je geen nieuwe Magento installatie opzetten. In plaats daarvan moet je daadwerkelijk alle bestanden en de database naar de nieuwe locatie verplaatsen.

Er zijn wel een aantal aandachtspunten waar je rekening mee moeten houden als je een Magento webwinkel op deze manier gaat verhuizen. Zo zul je in veel gevallen het bestand pear.ini (downloader/pearlib/pear.ini) moeten wijzigen om de MagentoConnect manager te laten werken.

Magento heeft hier een eenvoudig script voor beschikbaar gesteld die een nieuw pear.ini bestand voor je kan generen. Ik zelf vond het Magento script niet heel gebruiksvriendelijk en heb daarom een aantal verbeteringen aangebracht.

<?php

define('CR', "\r");
define('LF', "\n");
define('CRLF', CR . LF);

$contents = explode(LF, file_get_contents('pear.ini'));

$data = unserialize($contents[1]);

if(isset($data['bin_dir'])) {
	$oldPath = $data['bin_dir'];
	$newPath = getcwd();

	foreach($data as $key => $value) {
		if(is_string($value)) {
			$data[$key] = str_replace($oldPath, $newPath, $value);
		}
	}
}

?>
<!DOCTYPE html>

<html lang="en">
	<head>
		<meta charset="utf-8" />

		<title>Magento pear.ini generator | Pronamic</title>
	</head>

	<body>
		<h1>Magento pear.ini generator</h1>

		<h2>Paths</h2>

		<dl>
			<dt>Old path</dt>
			<dd>
				<?php if(isset($oldPath)): ?>
				<code><?php echo $oldPath; ?></code>
				<?php else: ?>
				<em>Unknown</em>
				<?php endif; ?>
			</dd>

			<dt>New path</dt>
			<dd>
				<?php if(isset($newPath)): ?>
				<code><?php echo $newPath; ?></code>
				<?php else: ?>
				<em>Unknown</em>
				<?php endif; ?>
			</dd>
		</dl>

		<h2>pear.ini</h2>

		<?php 

		$pearIni = $contents[0] . LF . serialize($data);

		?>
		<p>
			<textarea name="pear.ini" cols="80" rows="10"><?php echo $pearIni; ?></textarea>
		</p>
	</body>
</html>

Mocht je ooit een Mangeto webwinkel moeten verhuizen dan kan dit script zeker van pas komen!

WordPress GEO afstand

Op de website van Pronamic is in de voettekst een leuke GEO functionaliteit opgenomen:

In dit bericht zal ik beschrijven hoe je deze functionaliteit kunt toevoegen aan je eigen WordPress website. Allereerst voegen we aan footer.php de volgende code toe:

<div id="location-footer" class="geolocation">
	<?php get_template_part('geo', 'location-footer'); ?>
</div>

Vervolgens maken we binnen de theme map het bestand geo-location-footer.php aan. Binnen dit bestand plaatsen we de volgende code:

<?php

global $distanceToHQ;

if(isset($distanceToHQ) && $distanceToHQ < 50): ?>

Volgens GeoIP bent u minder dan 50 km verwijderd van een kopje koffie en een goed gesprek over internet. Kom vrijblijvend eens <a href="/contact/">bij ons langs</a>. Volgt u ons trouwens al op <a href="http://www.twitter.com/pronamic">Twitter</a>?

<?php else: ?>

Wij komen graag eens bij u langs voor een goed gesprek. Neem vrijblijvend <a href="/contact/">contact</a> met ons op. Volg ons op <a href="http://www.twitter.com/pronamic">Twitter</a>.
Bekijk onze foto's op <a href="http://www.flickr.com/groups/pronamic/">FlickR</a> of wordt lid van onze groep op <a href="http://pronamic.hyves.nl/">Hyves</a>.

<?php endif; ?>

Vervolgens voegen we de volgende code toe aan functions.php.

/**
 * Calculate distance between to points and return it in the specified unit
 */
function rt_calculate_distance($lat1, $lon1, $lat2, $lon2, $unit) {
	$theta = $lon1 - $lon2; 

	$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
	$dist = acos($dist);
	$dist = rad2deg($dist); 

	$miles = $dist * 60 * 1.1515;

	$unit = strtoupper($unit);

	if($unit == 'K') {
		return ($miles * 1.609344);
	} else if($unit == 'N') {
		return ($miles * 0.8684);
	} else {
		return $miles;
	}
}

/**
 * Calculate distance between to points and return it in the specified unit
 */
function rt_distance($location1, $location2, $unit) {
	return rt_calculate_distance($location1->latitude, $location1->longitude, $location2->latitude, $location2->longitude, $unit);
}

////////////////////////////////////////////////////////////

/**
 * AJAX
 */
function rt_ajax_geo() {
	$hqLocation = new stdClass();
	$hqLocation->latitude = 53.056079;
	$hqLocation->longitude = 6.200763;

	$clientLocation = new stdClass();
	$clientLocation->latitude = (float) filter_input(INPUT_POST, 'latitude', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
	$clientLocation->longitude = (float) filter_input(INPUT_POST, 'longitude', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);

	global $distanceToHQ;

	$distanceToHQ = rt_distance($hqLocation, $clientLocation, 'K');

	$element = filter_input(INPUT_POST, 'element', FILTER_SANITIZE_STRING);

	get_template_part('geo', $element);

	die();
}

add_action('wp_ajax_rt_geo', 'rt_ajax_geo');
add_action('wp_ajax_nopriv_rt_geo', 'rt_ajax_geo');

////////////////////////////////////////////////////////////

function rt_geo_scripts() {
	$key = 'INSERT-YOUR-KEY';

	wp_register_script('google-jsapi',
		'https://www.google.com/jsapi?key=' . $key
	);

	wp_register_script('rt-geo-script',
		get_bloginfo('template_directory') . '/js/geo.js' ,
		array('google-jsapi', 'jquery') ,
		'1.0'
	);

	wp_enqueue_script('rt-geo-script');
}

add_action('template_redirect', 'rt_geo_scripts');

Je moet voor het gebruik van deze functionaliteit een Google JS API key aanvragen. Vervang de tekst INSERT-YOUR-KEY in bovenstaande code met je eigen API key.

De laatste stap is om binnen je theme map het JavaScript bestand geo.js aan te maken in de map js met de volgende inhoud:

jQuery(document).ready(function($) {
	if($.isPlainObject(google.loader.ClientLocation)) {
		var clientLocation = google.loader.ClientLocation;

		$(".geolocation").each(function() {
			var element = $(this);

			var data = {
				action: "rt_geo" ,
				element: element.attr("id") ,
				latitude: clientLocation.latitude ,
				longitude: clientLocation.longitude
			};

			$.post("/wp-admin/admin-ajax.php", data, function(response) {
				element.html(response);
			});
		});
	}
});

Als het goed is zou je nu een dynamisch blok in je footer moeten hebben die geüpdate wordt zodra de afstand tussen de bezoeker en je locatie bekend is. Je kunt uiteraard geo-location-footer.php helemaal naar je eigen wens aanpassen. Daarnaast kun je een onbeperkt aantal GEO elementen toevoegen. Mocht je vragen, opmerkingen, verbeteringen, etc. hebben laat dan even een reactie achter!

WordPress Shopp plugin vertalingen (nl_NL)

Voor een opdracht bij Pronamic hebben we gebruik gemaakt van de WordPress Shopp plugin. Deze plugin tovert elke WordPress installatie om naar een eenvoudige webwinkel.
De plugin is ontwikkeld door Ingenesis Limited (weblog) een bedrijf uit Springfield (Ohio, Verenigde Staten).

De plugin is standaard alleen in het Engels beschikbaar. Gelukkig kan de plugin dankzij het WordPress vertaalmechanisme eenvoudige worden vertaald. Hiranthi
van Illutic WebDesign uit Enschede heeft al een Nederlandse vertaling op de Shopp website geplaatst.

Helaas was deze vertaling ietwat gedateerd en ontbrak het .PO bestand.
Gelukkig kunnen .MO bestanden eenvoudig omgezet worden naar .PO bestanden.
Als je gebruik maakt van Poedit kun je hiervoor
het volgende commando gebruiken:

C:\Program Files\Poedit\bin
msgunfmt Shopp-nl_NL.mo > Shopp-nl_NL.po

Vervolgens kun je binnen Poedit dit .PO bestand bijwerken naar het
recentste .POT bestand van de Shopp plugin.

Voor het gemak heb ik de .PO en .MO bestanden online gezet:

Helaas zijn de vertalingen nog niet volledig en up-to-date:

67% vertaald, 1256 teksten (216 onzeker, 0 ongeldige symbolen, 188 niet vertaald

OpenSSL fout Twinfield API

Een aantal weken terug wilde ik bij Pronamic wat experimenteren met de Twinfield API. De Twinfield API werkt met behulp van SOAP over een beveiligde HTTP verbinding. Volgens Twinfield zou je op de volgende manier een verbinding moeten kunnen maken:

$soapClient = new SoapClient('https://login.twinfield.com/webservices/session.asmx?wsdl', array('trace' => 1));

Helaas resulteerde het uitvoeren van bovenstaande PHP code in een foutmelding:

Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:14092073:SSL routines:SSL3_GET_SERVER_HELLO:bad packet length in Twinfield.php on line 8

Call Stack:
    0.0002     651112   1. {main}() Twinfield.php:0
    0.0003     651896   2. file_get_contents() Twinfield.php:8

Warning: file_get_contents(): Failed to enable crypto in Twinfield.php on line 8

Call Stack:
    0.0002     651112   1. {main}() Twinfield.php:0
    0.0003     651896   2. file_get_contents() Twinfield.php:8

Warning: file_get_contents(https://login.twinfield.com/webservices/session.asmx?wsdl): failed to open stream: operation failed in Twinfield.php on line 8

Call Stack:
    0.0002     651112   1. {main}() Twinfield.php:0
    0.0003     651896   2. file_get_contents() Twinfield.php:8

Fatal error: SoapClient::SoapClient(): 'uri' option is required in nonWSDL mode in Twinfield.php on line 13

Call Stack:
    0.0002     651112   1. {main}() Twinfield.php:0
    0.0686     653888   2. SoapClient->SoapClient() Twinfield.php:13

Dezelfde code werkte echter wel op een andere server, maar helaas niet op mijn ontwikkel- en test server. Dat was toch wel erg vervelend, daarom ben ik opzoek gegaan naar een oplossing. Ik kwam na een speurtocht al snel anderen tegen met vergelijkbare problemen. Zo rapporteerde ns@centralservices.nl een vergelijkbare fout in PHP’s bug tracking systeem.

Ik kon echter erg lastig een oplossing vinden voor het probleem. Ik las wel op verschillende websites dat het om een probleem in het OpenSSL pakket ging. Op mijn Debian ontwikkel- en test server had ik OpenSSL/0.9.8g geïnstalleerd. Dit is momenteel de stabiele versie van het OpenSSL pakket op het debian platform. Aangezien ik geen concrete oplossing kon vinden voor het probleem heb ik de test versie van OpenSSL geïnstalleerd.

Hiervoor heb ik eerst de volgende regels toegevoegd aan /etc/apt/sources.list.

deb http://ftp.nl.debian.org/debian squeeze main
deb-src http://ftp.nl.debian.org/debian/ squeeze main

Vervolgens heb ik OpenSSL en Apache opnieuw geïnstalleerd met behulp van de volgende commando’s:

# apt-get install openssl

# apt-get install apache

Sindsdien heb ik OpenSSL/0.9.8o draaien op mijn server en is mijn probleem opgelost. Ik kan nu zonder problemen de Twinfield SOAP API aanroepen.