Tag Archives: PHP

Caching Modules on PrestaShop

Let’s see an important examples: the category tree block (/modules/blockcategories.php)

i will show only the function that does the sql queries (that we are going to cache!).
Watch out for the Tools::getCache and Tools::setCache!

function hookLeftColumn($params)
{
	global $smarty, $cookie;

	/*  ONLY FOR THEME OLDER THAN v1.0 */
	global $link;

	//cache
	if (!$catOldTheme=Tools::getCache('blockCatOldTheme'.((!is_null($cookie->id_lang))?'_'.$cookie->id_lang:''))) //read cache
	{
		$catOldTheme=Category::getHomeCategories(intval($params['cookie']->id_lang), true);
		Tools::setCache('blockCatOldTheme'.((!is_null($cookie->id_lang))?'_'.$cookie->id_lang:''),$catOldTheme); //set cache
	}


	$smarty->assign(array(
		'categories' => $catOldTheme,
		'link' => $link
	));
	/* ELSE */

	$id_customer = intval($params['cookie']->id_customer);
	$maxdepth = Configuration::get('BLOCK_CATEG_MAX_DEPTH');

	//cache
	if (!$result=Tools::getCache('blockCatNewTheme'.((!is_null($cookie->id_lang))?'_'.$cookie->id_lang:''))) //read cache
	{
		$result=Db::getInstance()->ExecuteS('
		SELECT DISTINCT c.*, cl.*
		FROM `'._DB_PREFIX_.'category` c
		LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (c.`id_category` = cl.`id_category` AND `id_lang` = '.intval($params['cookie']->id_lang).')
		LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = c.`id_category`)
		WHERE 1'
		.(intval($maxdepth) != 0 ? ' AND `level_depth` <= '.intval($maxdepth) : '').'
		AND (c.`active` = 1 OR c.`id_category`= '.Configuration::get('PS_DB_macroCatIdHome').')
		AND cg.`id_group` '.(!$cookie->id_customer ?  '= 1' : 'IN (SELECT id_group FROM '._DB_PREFIX_.'customer_group WHERE id_customer = '.intval($cookie->id_customer).')').'
		ORDER BY `level_depth` ASC, cl.`name` ASC');
		Tools::setCache('blockCatNewTheme'.((!is_null($cookie->id_lang))?'_'.$cookie->id_lang:''),$result); //set cache
	}


	if (!$result)
		return;
	$resultParents = array();
	$resultIds = array();

	foreach ($result as $row)
	{
		$row['name'] = Category::hideCategoryPosition($row['name']);
		$resultParents[$row['id_parent']][] = $row;
		$resultIds[$row['id_category']] = $row;
	}

	$blockCategTree = $this->getTree($resultParents, $resultIds, Configuration::get('BLOCK_CATEG_MAX_DEPTH'));
	$isDhtml = (Configuration::get('BLOCK_CATEG_DHTML') == 1 ? true : false);
	$smarty->assign('isDhtml', $isDhtml);

	$this->currentCategoryId = NULL;
	if (isset($_GET['id_category']))
	{
		$cookie->last_visited_category = intval($_GET['id_category']);
		$this->currentCategoryId = intval($_GET['id_category']);
	}
	if (isset($_GET['id_product']))
	{
		if (!isset($cookie->last_visited_category) OR !Product::idIsOnCategoryId(intval($_GET['id_product']), array('0' => array('id_category' => $cookie->last_visited_category))))
		{
			$product = new Product(intval($_GET['id_product']));
			if (isset($product) AND Validate::isLoadedObject($product))
				$cookie->last_visited_category = intval($product->id_category_default);
		}
		$this->currentCategoryId = intval($cookie->last_visited_category);
	}

	$htmlOutput = $this->htmlTree($blockCategTree);
	$smarty->assign('htmlOutput', $htmlOutput);
	return $this->display(__FILE__, 'blockcategoriesnew.tpl');
}

with the first call, the getCache, we are checking if there is cached content on disk, and if it’s true, the cached content will be returned inside the $result variable.
If there is no cache content, the prestashop’s original code will run and the saved to disk with setCache method! easy uh?
The only thing that is missing is the deleting of this cached content (needed to update cached content with updated database data). I found to way to do this.

  • crontab: put a script that directly delete cached file on disk every hour/day (as you like)
  • right after database changes: put a delCache call inside postProcess() method definition on administration class (the ones that extends AdminTab) eg.: /admin/tabs/AdminCategories.php (we will see that more in details on last caching tutorial)
  • manually: delete cache manually when you have updated the interested records (in this example, the categories tables)

See you on next post to learn how cache modules!

Caching PrestaShop

hello everybody. actually i’m working for a webagency and i used prestashop to develop an ecommerce with over 3700 products and over 250 categories. pretty huge uh?

well prestashop it’s easy to develop and extend, but it’s not so optimized.. so it’s easy to run into slow queries and server freezes with over 1300 visitors per day. So i had to cache some of biggest queries, like categories tree and subcategories, blocks and products. With those expedients i lowered the number of queries from 200 per page to nearly 40 (there are a lot, i know.. but it’s prestashop, not my fault.)
so let’s start with the fixes! :)

first of all, let’s define two variable for our caching system, like the directory path of our cached content. open defines.inc.php and declare a variable, like i did

define('_SQL_CACHING_',  true); //set it to true to enable caching!
define('_PS_CACHE_DIR_',  __PS_BASE_URI__.'cache/'); //cache path!

then make that directory and give it write permissions.

then, let’s introduce some cache functions inside the Tools class file.

	static public function setCache($var,$data,$dir='sql/')
	{
		if (!_SQL_CACHING_) return;

		$path=_PS_CACHE_DIR_;

		$dir.=($var%100).'/'.$var.'/';
		$data=serialize($data);

		$path.=$dir;
		@mkdir($path,0777,true);
		@chmod($path,0777);
		$file=$path.$var.'.cache';

		@file_put_contents($file,$data);
		@chmod($file,0777);
	}

	static public function getCache($var,$dir='sql/')
	{
		if (!_SQL_CACHING_) return false;

		$path=_PS_CACHE_DIR_;

		$dir.=($var%100).'/'.$var.'/';
		$path.=$dir;
		$file=$path.$var.'.cache';

		if (file_exists($file))
		{
			$data=@file_get_contents($file);
			return unserialize($data);
		}
		else return false;
	}

	static public function delCache($var,$dir='sql/')
	{
		if (!_SQL_CACHING_) return false;

		if(!function_exists('rmdirr'))
		{
			function rmdirr($dir)
			{
				if (@file_exists($dir))
				{
					if (@is_dir($dir))
					{
						foreach(glob($dir."/*") as $obj)
							@is_dir($obj)? rmdirr($obj) : @unlink($obj);
						@rmdir($dir);
					}
					else @unlink($dir);
				}
			}
		}

		$path=_PS_CACHE_DIR_.$dir.($var%100).'/'.$var.'*';
		foreach(glob($path) as $filename)
			rmdirr($filename);
	}

let’s examine that functions.. we have:

  • setCache($var,$data,$dir=’sql/’): write cached data to disk
  • getCache($var,$dir=’sql/’): read cached data from disk
  • delCache($var,$dir=’sql/’): delete cached data from disk

how to use those function (parameters explaination)

  • $var: it’s the variable/file-on-disk name. it must be unique or a cached content will replace another one!
  • $data: it’s the data that we want to cache. it can be anything: simple variable, array, object..
  • $dir: it’s the subdirectory of cache path. I use it to differentiate caching path of blocks from main pages, for example.

where to use those functions?
well we have exactly three points where to use these functions: modules (on blocks), pages, single objects.

  • modules: we have to act inside the module files. normally the main file (same name of module’s directory)
  • pages: we have to act inside the files of prestashop’s root, like product.php or category.php and interact with smarty (the template engine)
  • objects: we have to act inside the ObjectModel class

On next posts i will show some examples that describes how to apply these kind of cache!

Projects that kept (and keep) me busy in these months

Hi everybody! I don’t know why i keep update this wordpress release but not post something new.. maybe i lack of inspiration or i just think that people don’t care (and me too). So, this is the first 2009 update, let’s start.

  1. NeXtRL.it FanZine
    I was six years old when i bought and read my first magazine, console magazine, and now i’m a sort of publisher of a community-made magazine, the NeXtRL.it Fanzine (started on December 2008). Here are the published issues.
    I made a lot of experience with both amateur (publisher 2007) and professional (quarkxpress) press software and i studied some way to share works (the written articles) and simplify human interactions with a “nothing-can-go-wrong” module (see point (2)). Now i’m working on the third issue of the fanzine and i’d like to do it with adobe indesign (another pro app) because i didn’t enjoy my experience with quarkxpress – complicated also on easy tasks like pick the right tool from the panel and no color picker!
  2. NeXtRL.it – Form to submit articles for the FanZine
    It’s a simple form with some javascript  that uses a validation engine (in javascript too) found on this tutorial. People can enter various type of articles, filling in the different fields that the chosen type of article requires. Then they can modify, delete or send (to themselves or to publisher – me) their ready-to-print articles. Then the articles arrive on my google docs account so i can share them with my collaborators that check for grammar errors and i finally i can paginate the final articles.
    I made it with php, mysql and IPB API because nextrl.it uses IPB Forum. So here it is the link, but you can’t access if you’re not logged in – and it’s all written in italian, too.
    Source code not available because i made it just for nextrl.it
  3. NeXtRL.it – Tournament script
    Here, i enanched an old script that i made adhoc for nextrl.it a year ago. It was messy and hardcoded, now it’s more flexible and still a bit messy 😛 I think i need to switch my php’s habits to OOP and start comment while (and not after) coding.
    Now the script can handle more than one tournament and of various type: ladders, points, victories. I rewritten quite the 95% of the code and it took me a week. This is the link and, also there, you can’t access if you’re not logged in and it’s in italian too.
    Source code not available because i made it just for nextrl.it
  4. Automata & Languages: Cocke-Younger-Kasami Parser
    I made this parser in a month for university purpose. I will post and explain the code when i will pass the related exam, so here there are some info form wikipedia. Basically, i did a program that manipulate a context-free grammar to eliminate epsilon production, unit production, put it in chomsky normal form and last parse a word with CYK algorithm and say if it belong, or not, to the given grammar.
    Made with Java (instead of C++) for it’s wide library of string manipulation functions.
  5. ns2/nsmiracle
    I started to study about my thesis: understand how ns2 and nsmiracle modules are written to implement specific ones. Next monday (the 18th of May 2009) i will know more about those modules.
  6. WWTBAFM: new release?
    I though two times about release a new version of wwtbafm: two separated homebrew, one to play and the other to update questions. when i’ll have time and i will get my nds back i would give it a try, now that palibs are fixed to work with latest ndslib

That’s all, let’s hope more updates soon :)

UPDATE: oh, well, i forgot to mention that i have also build a simple rs232-ttl interface to mod my x360. I will post schema and how-to on next post :)

WWTBAFM OQM – Offline Questions Manager :)

YvanSoftware is coding an offline questions writer for WWTBAFM! that’s very cool for who want to develop questions without access to internet. if you want to add the questions written with this software, you must email me the questions file, specifying the language, and i’ll add it to the database :)

here it is the website of this nice project!

who wants to do a new gfx?

i don’t want to wait anymore. everyone that want to help this project can try to do a gfx and starts hope that it will be the official skin of WWTBAFM. This will be a sort of contest. You can send your work at lottiATfastwebnetDOTit. Then i’ll post all the entries and people will choose (by vote) the best skin. :)

SOME SPECS:
read the first 3-4 paragraphs of palib’s sprites tutorials

Chiip Programmer

Yesterday night i did the chiip programmer:

  • if you don’t know how to cut the plastic, just use a red-hot knife
  • use thin wires. but not too much thin! (mine wires were too much thin. very difficult to solder in that small space)
  • study (before soldering) the components positions. remember that you’ll have to close that box!
  • if your socket’s pins are too short, solder wires to pins and then pass the wires inside the box

Well, now i just need one or two atmega8L8.. but i can’t find it in Rome.. if you want to help me, buy 1 or 2 atmega8L8 and send them to me. i’ll pay you for chips/shipping/time :)

Here some photos.

MancalaDS 1.5 nearly done


another night has nearly gone and mancalaDS it’s growing very fast.
This night i added the possibility to choose how many beans to start with. it was a gbarl user suggestion, at this time i can’t remember who asked for it. I predispose the game structure to fit the singleplayer game too. All it’s ready and working.. what it misses? the AI.. i think i could develop it well after some nice hours of sleep.

hey guys! take a look to tagDS it’s a very nice 2player game made by tassu. [download here]

Dat Manager is out!

today i wrote a dat manager (for nintendo ds, compatible with offline list) that works with php and mysql (only 1 table). it’s pretty basic but it works well. it uses smarty (as template manager). if you want to take a look to it or just take a copy of source code to build your own nintendo ds dat file, simple ask me about it.
lotti AT fastwebnet DOT it

improving the md5 encryption!

hello guys :) today i studied a very simple method to improve the md5 protection against all available vocabulary attacks that are popping out in these months.
it’s very simple. it consists of add 2 or more md5 hash (for example, the password plus username plus date of registration) char by char.

now we got a new hash string that doesn’t appears like a normal hash (isn’t hexadecimal). so what we need to do now? simple! just re-encrypt this strange hash.

now we got particular hash that can’t return in any way the username nor password nor date of registration.

here’s the sample code:
————————–

<form method=”post”>
username: <input name=”username”> <br>
password: <input name=”password”><br>
<input name=”data”><br>
<br>
<?
$username=$_POST[“username”];
$password=$_POST[“password”];
$data=$_POST[“data”];
$sum=””;

$md5username=md5($username);
$md5password=md5($password);
$md5data=md5($data);

for($i=0;$i<32;$i++)
$sum.=chr(ord($md5username[$i])+ord($md5password[$i])+ord($md5data[$i]));

$hash=md5($sum);

echo “hash di “.$username.”: “.$md5username.”<br>”;
echo “hash di “.$password.”: “.$md5password.”<br>”;
echo “hash di “.$data.”: “.$md5data.”<br>”;
echo “somma degli hash: “.$sum.”<br>”;
echo “hash della somma: “.$hash.”<br>”;

?>
<br>
<br>
LOGIN <br>
username: <input name=”l1″> <br>
password: <input name=”l2″><br>
<input name=”l3″><br>
<input type=”submit”><br>
</form>

<?

$l1=$_POST[“l1”];
$l2=$_POST[“l2”];
$l3=$_POST[“l3″];
$l4=””;

$md5l1=md5($l1);
$md5l2=md5($l2);
$md5l3=md5($l3);

for($i=0;$i<32;$i++)
$l4.=chr(ord($md5l1[$i])+ord($md5l2[$i])+ord($md5l3[$i]));

$hashl4=md5($l4);

if ($hashl4==$hash) echo “login succesful”;
else echo “login denied”;

?>