diff --git a/php/classes/CatIntervalCacheObject.php b/php/classes/CatIntervalCacheObject.php
deleted file mode 100644
index 67d581a..0000000
--- a/php/classes/CatIntervalCacheObject.php
+++ /dev/null
@@ -1,105 +0,0 @@
-<?php
-
-class CatIntervalCacheObject extends IntervalCacheObject
-{
-	// for catalog
-	private $params      = array();
-
-	public function toArray()
-	{
-		$result = array(
-			"cacheId" => $this->id,
-			"start"   => $this->getStartToISO(),
-			"stop"    => $this->getStopToISO()
-		);
-		if ($this->isNew)
-			$result["isNew"] = true;
-
-		if ($this->isModified)
-			$result["isModified"] = true;
-
-		for ($i = 0; $i < count($this->params); $i++)
-		{
-			$paramObject = array();
-			$index = 'param'.sprintf("%d",$i+2);
-			$result[$index] = $this->params[$i];
-		}
-		return $result;
-	}
-
-	// for catalog
-	public function setParams($params)
-	{
-		$this->params = $params;
-	}
-
-	public function getParams()
-	{
-	   return $this->params;
-	}
-
-	public function writeBin($handle, $paramsNumber, $paramsSizes, $paramsTypes)
-	{
-		fwrite($handle,pack('L6',$this->id,$this->index,$this->start,$this->stop,$this->isNew,$this->isModified));
-		for ($i = 0; $i < $paramsNumber; $i++)
-		{
-			if ($paramsTypes[$i] == '2') // string
-			{
-				fwrite($handle,pack('d', strlen($this->params[$i])));
-				fwrite($handle, $this->params[$i],strlen($this->params[$i]));
-			}
-			else
-			{
-				if ($paramsTypes[$i] == '1')
-						$paramString = TimeUtils::iso2stamp($this->params[$i]);
-				else
-						$paramString = $this->params[$i];
-
-				$paramArray =  explode(',',$paramString);
-				for ($j = 0; $j < $paramsSizes[$i]; $j++) fwrite($handle,pack('d', $paramArray[$j]));
-			}
-		}
-	}
-
-	public function loadBin($handle, $paramsNumber, $paramsSizes, $paramsTypes)
-	{
-		$array = unpack('L6int',fread($handle,6*4));
-		$this->id         = $array['int1'];
-		$this->index      = $array['int2'];
-		$this->start      = $array['int3'];
-		$this->stop       = $array['int4'];
-		$this->isNew      = $array['int5'];
-		$this->isModified = $array['int6'];
-
-		for ($i = 0; $i < $paramsNumber; $i++) {
-		  $this->params[$i] = null;
-
-		  for ($j = 0; $j < $paramsSizes[$i]; $j++)
-		  {
-				$val = unpack('dval',fread($handle,8));
-
-				if ($paramsTypes[$i] == '2') // string
-				{
-					$this->params[$i] = fread($handle,$val['val']);
-				}
-				else
-				{
-					if ($paramsTypes[$i] == '1')
-						$this->params[$i] .= TimeUtils::stamp2iso($val['val']);
-					else
-						$this->params[$i] .= $val['val'];
-
-					if ($j != $paramsSizes[$i] - 1) $this->params[$i] .= ',';
-				}
-			}
-		}
-
-	}
-
-	public function dump()
-	{
-		echo " => Interval : id = ".$this->id.", index = ".$this->index.", start = ".$this->start.", stop = ".$this->stop.", isNew = ".$this->isNew.", isModified = ".$this->isModified.PHP_EOL;
-	}
-}
-
- ?>
diff --git a/php/classes/CatalogCacheIntervalObject.php b/php/classes/CatalogCacheIntervalObject.php
new file mode 100644
index 0000000..d5b5358
--- /dev/null
+++ b/php/classes/CatalogCacheIntervalObject.php
@@ -0,0 +1,105 @@
+<?php
+
+class CatalogCacheIntervalObject extends TimeTableCacheIntervalObject
+{
+	// for catalog
+	private $params      = array();
+
+	public function toArray()
+	{
+		$result = array(
+			"cacheId" => $this->id,
+			"start"   => $this->getStartToISO(),
+			"stop"    => $this->getStopToISO()
+		);
+		if ($this->isNew)
+			$result["isNew"] = true;
+
+		if ($this->isModified)
+			$result["isModified"] = true;
+
+		for ($i = 0; $i < count($this->params); $i++)
+		{
+			$paramObject = array();
+			$index = 'param'.sprintf("%d",$i+2);
+			$result[$index] = $this->params[$i];
+		}
+		return $result;
+	}
+
+	// for catalog
+	public function setParams($params)
+	{
+		$this->params = $params;
+	}
+
+	public function getParams()
+	{
+	   return $this->params;
+	}
+
+	public function writeBin($handle, $paramsNumber, $paramsSizes, $paramsTypes)
+	{
+		fwrite($handle,pack('L6',$this->id,$this->index,$this->start,$this->stop,$this->isNew,$this->isModified));
+		for ($i = 0; $i < $paramsNumber; $i++)
+		{
+			if ($paramsTypes[$i] == '2') // string
+			{
+				fwrite($handle,pack('d', strlen($this->params[$i])));
+				fwrite($handle, $this->params[$i],strlen($this->params[$i]));
+			}
+			else
+			{
+				if ($paramsTypes[$i] == '1')
+						$paramString = TimeUtils::iso2stamp($this->params[$i]);
+				else
+						$paramString = $this->params[$i];
+
+				$paramArray =  explode(',',$paramString);
+				for ($j = 0; $j < $paramsSizes[$i]; $j++) fwrite($handle,pack('d', $paramArray[$j]));
+			}
+		}
+	}
+
+	public function loadBin($handle, $paramsNumber, $paramsSizes, $paramsTypes)
+	{
+		$array = unpack('L6int',fread($handle,6*4));
+		$this->id         = $array['int1'];
+		$this->index      = $array['int2'];
+		$this->start      = $array['int3'];
+		$this->stop       = $array['int4'];
+		$this->isNew      = $array['int5'];
+		$this->isModified = $array['int6'];
+
+		for ($i = 0; $i < $paramsNumber; $i++) {
+		  $this->params[$i] = null;
+
+		  for ($j = 0; $j < $paramsSizes[$i]; $j++)
+		  {
+				$val = unpack('dval',fread($handle,8));
+
+				if ($paramsTypes[$i] == '2') // string
+				{
+					$this->params[$i] = fread($handle,$val['val']);
+				}
+				else
+				{
+					if ($paramsTypes[$i] == '1')
+						$this->params[$i] .= TimeUtils::stamp2iso($val['val']);
+					else
+						$this->params[$i] .= $val['val'];
+
+					if ($j != $paramsSizes[$i] - 1) $this->params[$i] .= ',';
+				}
+			}
+		}
+
+	}
+
+	public function dump()
+	{
+		echo " => Interval : id = ".$this->id.", index = ".$this->index.", start = ".$this->start.", stop = ".$this->stop.", isNew = ".$this->isNew.", isModified = ".$this->isModified.PHP_EOL;
+	}
+}
+
+ ?>
diff --git a/php/classes/CatalogCacheObject.php b/php/classes/CatalogCacheObject.php
index 082df0e..89290b3 100644
--- a/php/classes/CatalogCacheObject.php
+++ b/php/classes/CatalogCacheObject.php
@@ -8,7 +8,7 @@ class CatalogCacheObject extends TimeTableCacheObject
 
 	public function addInterval($startIso, $stopIso, $params, $isNew = false, $index = -1)
 	{
-		$interval = new CatIntervalCacheObject($this->lastId, count($this->intervals));
+		$interval = new CatalogCacheIntervalObject($this->lastId, count($this->intervals));
 		++$this->lastId;
 		$interval->setStartFromISO($startIso);
 		$interval->setStopFromISO($stopIso);
@@ -150,7 +150,7 @@ class CatalogCacheObject extends TimeTableCacheObject
 
 		for ($i = 0; $i < $nbIntervals; ++$i)
 		{
-			$interval = new CatIntervalCacheObject(-1);
+			$interval = new CatalogCacheIntervalObject(-1);
 			$interval->loadBin($handle, $this->paramsNumber, $this->paramsSizes, $this->paramsTypes);
 			array_push($this->intervals, $interval);
 		}
diff --git a/php/classes/FilterCacheObject.php b/php/classes/FilterCacheObject.php
deleted file mode 100644
index cb6d958..0000000
--- a/php/classes/FilterCacheObject.php
+++ /dev/null
@@ -1,286 +0,0 @@
-<?php
-
-class FilterPartCacheObject
-{
-	public static $TYPE_UNKNOWN       = 0;
-	public static $TYPE_START         = 1;
-	public static $TYPE_STOP          = 2;
-	public static $TYPE_DURATION_SEC  = 3;
-	public static $TYPE_DURATION_MIN  = 4;
-	public static $TYPE_DURATION_HOUR = 5;
-
-	public static $OPERATION_UNKNOWN   = 0;
-	public static $OPERATION_LT        = 1;
-	public static $OPERATION_GT        = 2;
-	public static $OPERATION_EQ        = 3;
-
-	protected $type;
-	protected $op;
-	protected $value;
-
-	function __construct() {
-		$this->type  = self::$TYPE_UNKNOWN;
-		$this->op    = self::$OPERATION_UNKNOWN;
-		$this->value = 0.;
-	}
-
-	public function getType() {
-		return $this->type;
-	}
-
-	public function getOp() {
-		return $this->op;
-	}
-
-	public function getValue() {
-		return $this->value;
-	}
-
-	public function isSame($part) {
-		return (($this->type == $part->getType()) && ($this->op == $part->getOp()) && ($this->value == $part->getValue()));
-	}
-
-	public function toFiltered($interval) {
-		switch ($this->type) {
-			case self::$TYPE_START :
-				{
-					switch ($this->op) {
-						case self::$OPERATION_LT :
-							return ($interval->getStartToStamp() < $this->value);
-						case self::$OPERATION_GT :
-							return ($interval->getStartToStamp() > $this->value);
-						case self::$OPERATION_EQ :
-							return (!(($interval->getStartToStamp() >= $this->value) && ($interval->getStartToStamp() <= $this->value+86400)));
-						default :
-							return false;
-					}
-				}
-				break;
-			case self::$TYPE_STOP :
-				{
-					switch ($this->op) {
-						case self::$OPERATION_LT :
-							return ($interval->getStopToStamp() < $this->value);
-						case self::$OPERATION_GT :
-							return ($interval->getStopToStamp() > $this->value);
-						case self::$OPERATION_EQ :
-							return (!(($interval->getStopToStamp() >= $this->value) && ($interval->getStopToStamp() <= $this->value+86400)));
-						default :
-							return false;
-					}
-				}
-				break;
-			case self::$TYPE_DURATION_SEC :
-			case self::$TYPE_DURATION_MIN :
-			case self::$TYPE_DURATION_HOUR :
-				{
-					$value = $this->value;
-					if ($this->type == self::$TYPE_DURATION_MIN)
-						$value *= 60;
-					else if ($this->type == self::$TYPE_DURATION_HOUR)
-						$value *= 3600;
-					switch ($this->op) {
-						case self::$OPERATION_LT :
-							return ($interval->getDuration() < $value);
-						case self::$OPERATION_GT :
-							return ($interval->getDuration() > $value);
-						case self::$OPERATION_EQ :
-							return ($interval->getDuration() != $value);
-						default :
-							return false;
-					}
-				}
-				break;
-			default:
-				return false;
-		}
-	}
-
-	public function loadFromObject($part_obj) {
-		$this->value = 0.;
-		switch ($part_obj->field)
-		{
-			case 'start'        :
-				$this->value = TimeUtils::iso2stamp($part_obj->value);
-				$this->type = self::$TYPE_START;
-				break;
-			case 'stop'         :
-				$this->value = TimeUtils::iso2stamp($part_obj->value);
-				$this->type = self::$TYPE_STOP;
-				break;
-			case 'durationMin'  :
-				$this->value = $part_obj->value;
-				$this->type = self::$TYPE_DURATION_MIN;
-				break;
-			case 'durationHour' :
-				$this->value = $part_obj->value;
-				$this->type = self::$TYPE_DURATION_HOUR;
-				break;
-			case 'durationSec'  :
-				$this->value = $part_obj->value;
-				$this->type = self::$TYPE_DURATION_SEC;
-				break;
-			default:
-				$this->value = 0.;
-				$this->type = self::$TYPE_UNKNOWN;
-		}
-
-		switch ($part_obj->comparison)
-		{
-			case 'lt' :
-				$this->op = self::$OPERATION_LT;
-				break;
-			case 'gt' :
-				$this->op = self::$OPERATION_GT;
-				break;
-			case 'eq' :
-				$this->op = self::$OPERATION_EQ;
-				break;
-			default:
-				$this->op = self::$OPERATION_UNKNOWN;
-		}
-	}
-
-	public function writeBin($handle) {
-		fwrite($handle,pack('L2',$this->type,$this->op));
-		fwrite($handle,pack('f',$this->value));
-	}
-
-	public function loadBin($handle) {
-		$res = unpack('L2data',fread($handle,4*2));
-		$this->type = $res['data1'];
-		$this->op   = $res['data2'];
-
-		$res = unpack('fvalue',fread($handle,4));
-		$this->value = $res['value'];
-	}
-
-	public function dump() {
-		echo "   => FilterPartCacheObject : type = ";
-		switch ($this->type)
-		{
-			case self::$TYPE_START :
-				echo "start";
-				break;
-			case self::$TYPE_STOP :
-				echo "stop";
-				break;
-			case self::$TYPE_DURATION_SEC :
-				echo "duration seconde";
-				break;
-			case self::$TYPE_DURATION_MIN :
-				echo "duration minute";
-				break;
-			case self::$TYPE_DURATION_HOUR :
-				echo "duration hour";
-				break;
-			default:
-				echo "unknown";
-		}
-		echo ", operation = ";
-		switch ($this->op)
-		{
-			case self::$OPERATION_LT :
-				echo "lt";
-				break;
-			case self::$OPERATION_GT :
-				echo "gt";
-				break;
-			case self::$OPERATION_EQ :
-				echo "eq";
-				break;
-			default:
-				echo "unknown";
-		}
-		echo ", value = ".$this->value.PHP_EOL;
-	}
-}
-
-class FilterCacheObject
-{
-	protected $parts = array();
-
-	function __construct() {
-
-	}
-
-	public function getParts() {
-		return $this->parts;
-	}
-
-	public function reset() {
-		$this->parts = array();
-	}
-
-	public function isEmpty() {
-		return (count($this->parts) == 0);
-	}
-
-	public function loadFromJSON($filter_json) {
-		$this->reset();
-		$filter_obj = json_decode($filter_json);
-
-		foreach ($filter_obj as $filter_part)
-		{
-			$part = new FilterPartCacheObject();
-			$part->loadFromObject($filter_part);
-			array_push($this->parts, $part);
-		}
-	}
-
-	public function isSame($filter) {
-		if (count($this->parts) != count($filter->getParts()))
-			return false;
-
-		$identique = true;
-		for ($i = 0; $i < count($this->parts); ++$i)
-		{
-			if (!$this->parts[$i]->isSame($filter->getParts()[$i]))
-			{
-				return false;
-			}
-		}
-
-		return true;
-	}
-
-	public function isSameFromJSON($filter_json) {
-		$filter = new FilterCacheObject();
-		$filter->loadFromJSON($filter_json);
-		return $this->isSame($filter);
-	}
-
-	public function toFiltered($interval) {
-		foreach ($this->parts as $part)
-		{
-			if ($part->toFiltered($interval))
-				return true;
-		}
-		return false;
-	}
-
-	public function writeBin($handle) {
-		fwrite($handle,pack('L',count($this->parts)));
-		foreach ($this->parts as $part)
-			$part->writeBin($handle);
-	}
-
-	public function loadBin($handle) {
-		$this->reset();
-		$res = unpack('Lcount',fread($handle,4));
-		for ($i = 0; $i < $res['count']; ++$i)
-		{
-			$part = new FilterPartCacheObject();
-			$part->loadBin($handle);
-			array_push($this->parts, $part);
-		}
-	}
-
-	public function dump() {
-		echo " => FilterCacheObject : number of parts = ".count($this->parts).PHP_EOL;
-		foreach ($this->parts as $part)
-			$part->dump();
-	}
-}
-
- ?>
diff --git a/php/classes/IntervalCacheObject.php b/php/classes/IntervalCacheObject.php
deleted file mode 100644
index b715093..0000000
--- a/php/classes/IntervalCacheObject.php
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-class IntervalCacheObject
-{
-	protected $id         = -1;
-	protected $index      = -1;
-	protected $start      = 0;
-	protected $stop       = 0;
-	protected $isNew      = false;
-	protected $isModified = false;
-
-	function __construct($id, $index = -1) {
-		$this->id = $id;
-		$this->index = $index;
-	}
-
-	public function getId() {
-		return $this->id;
-	}
-
-	public function getIndex() {
-		return $this->index;
-	}
-
-	public function setIndex($index) {
-		$this->index = $index;
-	}
-
-	public function getStartToStamp() {
-		return $this->start;
-	}
-
-	public function getStartToISO() {
-		return TimeUtils::stamp2iso($this->start);
-	}
-
-	public function setStartFromStamp($stamp) {
-		$this->start = $stamp;
-	}
-
-	public function setStartFromISO($iso) {
-		$this->start = TimeUtils::iso2stamp($iso);
-	}
-
-	public function getStopToStamp() {
-		return $this->stop;
-	}
-
-	public function getStopToISO() {
-		return TimeUtils::stamp2iso($this->stop);
-	}
-
-	public function setStopFromStamp($stamp) {
-		$this->stop = $stamp;
-	}
-
-	public function setStopFromISO($iso) {
-		$this->stop = TimeUtils::iso2stamp($iso);
-	}
-
-	public function getDuration() {
-		return ($this->stop-$this->start);
-	}
-
-	public function isModified() {
-		return $this->isModified;
-	}
-
-	public function setIsModified($isModified) {
-		$this->isModified = $isModified;
-	}
-
-	public function isNew() {
-		return $this->isNew;
-	}
-
-	public function setIsNew($isNew) {
-		$this->isNew = $isNew;
-	}
-
-	public function toArray() {
-		$result = array(
-			"cacheId" => $this->id,
-			"start"   => $this->getStartToISO(),
-			"stop"    => $this->getStopToISO()
-		);
-		if ($this->isNew)
-			$result["isNew"] = true;
-		if ($this->isModified)
-			$result["isModified"] = true;
-
-		return $result;
-	}
-
-
-
-	public function writeBin($handle) {
-		fwrite($handle,pack('L6',$this->id,$this->index,$this->start,$this->stop,$this->isNew,$this->isModified));
-	}
-
-	public function loadBin($handle) {
-		$array = unpack('L6int',fread($handle,6*4));
-		$this->id         = $array['int1'];
-		$this->index      = $array['int2'];
-		$this->start      = $array['int3'];
-		$this->stop       = $array['int4'];
-		$this->isNew      = $array['int5'];
-		$this->isModified = $array['int6'];
-	}
-
-	public function dump() {
-		echo " => Interval : id = ".$this->id.", index = ".$this->index.", start = ".$this->start.", stop = ".$this->stop.", isNew = ".$this->isNew.", isModified = ".$this->isModified.PHP_EOL;
-	}
-}
-?>
diff --git a/php/classes/SortCacheObject.php b/php/classes/SortCacheObject.php
deleted file mode 100644
index d837d12..0000000
--- a/php/classes/SortCacheObject.php
+++ /dev/null
@@ -1,261 +0,0 @@
-<?php
-
-class SortPartCacheObject
-{
-	public static $TYPE_UNKNOWN       = 0;
-	public static $TYPE_START         = 1;
-	public static $TYPE_STOP          = 2;
-	public static $TYPE_DURATION_SEC  = 3;
-	public static $TYPE_DURATION_MIN  = 4;
-	public static $TYPE_DURATION_HOUR = 5;
-
-	public static $DIRECTION_UNKNOWN = 0;
-	public static $DIRECTION_ASC     = 1;
-	public static $DIRECTION_DES     = 2;
-
-	protected $type;
-	protected $dir;
-
-	function __construct() {
-		$this->type = self::$TYPE_UNKNOWN;
-		$this->dir  = self::$DIRECTION_UNKNOWN;
-	}
-
-	public function getType() {
-		return $this->type;
-	}
-
-	public function getDir() {
-		return $this->dir;
-	}
-
-	public function isSame($part) {
-		return (($this->type == $part->getType()) && ($this->dir == $part->getDir()));
-	}
-
-	public function compare($interval_a, $interval_b) {
-		switch ($this->type) {
-			case self::$TYPE_START :
-				{
-					switch ($this->dir) {
-						case self::$DIRECTION_ASC :
-							return ($interval_b->getStartToStamp() - $interval_a->getStartToStamp());
-						default :
-							return ($interval_a->getStartToStamp() - $interval_b->getStartToStamp());
-					}
-				}
-				break;
-			case self::$TYPE_STOP :
-				{
-					switch ($this->dir) {
-						case self::$DIRECTION_ASC :
-							return ($interval_b->getStopToStamp() - $interval_a->getStopToStamp());
-						default :
-							return ($interval_a->getStopToStamp() - $interval_b->getStopToStamp());
-					}
-				}
-				break;
-			case self::$TYPE_DURATION_SEC :
-			case self::$TYPE_DURATION_MIN :
-			case self::$TYPE_DURATION_HOUR :
-				{
-					switch ($this->dir) {
-						case self::$DIRECTION_ASC :
-							return ($interval_b->getDuration() - $interval_a->getDuration());
-						default :
-							return ($interval_a->getDuration() - $interval_b->getDuration());
-					}
-				}
-				break;
-			default :
-				return 0;
-		}
-		return 0;
-	}
-
-	public function loadFromObject($part_obj) {
-		switch ($part_obj->property)
-		{
-			case 'start'        :
-				$this->type = self::$TYPE_START;
-				break;
-			case 'stop'         :
-				$this->type = self::$TYPE_STOP;
-				break;
-			case 'durationMin'  :
-				$this->type = self::$TYPE_DURATION_MIN;
-				break;
-			case 'durationHour' :
-				$this->type = self::$TYPE_DURATION_HOUR;
-				break;
-			case 'durationSec'  :
-				$this->type = self::$TYPE_DURATION_SEC;
-				break;
-			default:
-				$this->type = self::$TYPE_UNKNOWN;
-		}
-
-		switch ($part_obj->direction)
-		{
-			case 'ASC' :
-				$this->dir = self::$DIRECTION_ASC;
-				break;
-			case 'DESC' :
-				$this->dir = self::$DIRECTION_DES;
-				break;
-			default:
-				$this->dir = self::$DIRECTION_UNKNOWN;
-		}
-	}
-
-	public function writeBin($handle) {
-		fwrite($handle,pack('L2',$this->type,$this->dir));
-	}
-
-	public function loadBin($handle) {
-		$res = unpack('L2data',fread($handle,4*2));
-		$this->type = $res['data1'];
-		$this->dir   = $res['data2'];
-	}
-
-	public function dump() {
-		echo "   => SortPartCacheObject : type = ";
-		switch ($this->type)
-		{
-			case self::$TYPE_START :
-				echo "start";
-				break;
-			case self::$TYPE_STOP :
-				echo "stop";
-				break;
-			case self::$TYPE_DURATION_SEC :
-				echo "duration seconde";
-				break;
-			case self::$TYPE_DURATION_MIN :
-				echo "duration minute";
-				break;
-			case self::$TYPE_DURATION_HOUR :
-				echo "duration hour";
-				break;
-			default:
-				echo "unknown";
-		}
-		echo ", direction = ";
-		switch ($this->dir)
-		{
-			case self::$DIRECTION_ASC :
-				echo "ASC";
-				break;
-			case self::$DIRECTION_DES :
-				echo "DESC";
-				break;
-			default:
-				echo "unknown";
-		}
-		echo PHP_EOL;
-	}
-}
-
-class SortCacheObject
-{
-	protected $parts = array();
-
-	function __construct() {
-	}
-
-	public function getParts() {
-		return $this->parts;
-	}
-
-	public function reset() {
-		$this->parts = array();
-	}
-
-	public function isEmpty() {
-		return (count($this->parts) == 0);
-	}
-
-	public function loadFromObject($sort_obj) {
-		$this->reset();
-		foreach ($sort_obj as $sort_part)
-		{
-			$part = new SortPartCacheObject();
-			$part->loadFromObject($sort_part);
-			array_push($this->parts, $part);
-		}
-	}
-
-	public function isSameFromObject($sort_obj) {
-		$sort = new SortCacheObject();
-		$sort->loadFromObject($sort_obj);
-		return $this->isSame($sort);
-	}
-
-	public function isSame($sort) {
-		if (count($this->parts) != count($sort->getParts()))
-			return false;
-
-		$identique = true;
-		for ($i = 0; $i < count($this->parts); ++$i)
-		{
-			if (!$this->parts[$i]->isSame($sort->getParts()[$i]))
-			{
-				return false;
-			}
-		}
-
-		return true;
-	}
-
-	public function apply($intervals) {
-		$sorted_indexes = array();
-
-		global $global_parts, $global_intervals;
-		$global_parts = $this->parts;
-		$global_intervals = $intervals;
-
-		foreach ($intervals as $interval)
-			array_push($sorted_indexes, $interval->getIndex());
-
-		if (count($global_parts) == 0)
-			return $sorted_indexes;
-
-		usort($sorted_indexes, function ($index_a, $index_b) {
-			global $global_parts, $global_intervals;
-			foreach ($global_parts as $part)
-			{
-				$res = $part->compare($global_intervals[$index_a], $global_intervals[$index_b]);
-				if ($res != 0)
-					return $res;
-			}
-			return $index_a-$index_b;
-		});
-
-		return $sorted_indexes;
-	}
-
-	public function writeBin($handle) {
-		fwrite($handle,pack('L',count($this->parts)));
-		foreach ($this->parts as $part)
-			$part->writeBin($handle);
-	}
-
-	public function loadBin($handle) {
-		$this->reset();
-		$res = unpack('Lcount',fread($handle,4));
-		for ($i = 0; $i < $res['count']; ++$i)
-		{
-			$part = new SortPartCacheObject();
-			$part->loadBin($handle);
-			array_push($this->parts, $part);
-		}
-	}
-
-	public function dump() {
-		echo " => SortCacheObject : number of parts = ".count($this->parts).PHP_EOL;
-		foreach ($this->parts as $part)
-			$part->dump();
-	}
-}
-
- ?>
diff --git a/php/classes/TimeTableCacheFilterObject.php b/php/classes/TimeTableCacheFilterObject.php
new file mode 100644
index 0000000..282b461
--- /dev/null
+++ b/php/classes/TimeTableCacheFilterObject.php
@@ -0,0 +1,286 @@
+<?php
+
+class TimeTableCacheFilterPartObject
+{
+	public static $TYPE_UNKNOWN       = 0;
+	public static $TYPE_START         = 1;
+	public static $TYPE_STOP          = 2;
+	public static $TYPE_DURATION_SEC  = 3;
+	public static $TYPE_DURATION_MIN  = 4;
+	public static $TYPE_DURATION_HOUR = 5;
+
+	public static $OPERATION_UNKNOWN   = 0;
+	public static $OPERATION_LT        = 1;
+	public static $OPERATION_GT        = 2;
+	public static $OPERATION_EQ        = 3;
+
+	protected $type;
+	protected $op;
+	protected $value;
+
+	function __construct() {
+		$this->type  = self::$TYPE_UNKNOWN;
+		$this->op    = self::$OPERATION_UNKNOWN;
+		$this->value = 0.;
+	}
+
+	public function getType() {
+		return $this->type;
+	}
+
+	public function getOp() {
+		return $this->op;
+	}
+
+	public function getValue() {
+		return $this->value;
+	}
+
+	public function isSame($part) {
+		return (($this->type == $part->getType()) && ($this->op == $part->getOp()) && ($this->value == $part->getValue()));
+	}
+
+	public function toFiltered($interval) {
+		switch ($this->type) {
+			case self::$TYPE_START :
+				{
+					switch ($this->op) {
+						case self::$OPERATION_LT :
+							return ($interval->getStartToStamp() < $this->value);
+						case self::$OPERATION_GT :
+							return ($interval->getStartToStamp() > $this->value);
+						case self::$OPERATION_EQ :
+							return (!(($interval->getStartToStamp() >= $this->value) && ($interval->getStartToStamp() <= $this->value+86400)));
+						default :
+							return false;
+					}
+				}
+				break;
+			case self::$TYPE_STOP :
+				{
+					switch ($this->op) {
+						case self::$OPERATION_LT :
+							return ($interval->getStopToStamp() < $this->value);
+						case self::$OPERATION_GT :
+							return ($interval->getStopToStamp() > $this->value);
+						case self::$OPERATION_EQ :
+							return (!(($interval->getStopToStamp() >= $this->value) && ($interval->getStopToStamp() <= $this->value+86400)));
+						default :
+							return false;
+					}
+				}
+				break;
+			case self::$TYPE_DURATION_SEC :
+			case self::$TYPE_DURATION_MIN :
+			case self::$TYPE_DURATION_HOUR :
+				{
+					$value = $this->value;
+					if ($this->type == self::$TYPE_DURATION_MIN)
+						$value *= 60;
+					else if ($this->type == self::$TYPE_DURATION_HOUR)
+						$value *= 3600;
+					switch ($this->op) {
+						case self::$OPERATION_LT :
+							return ($interval->getDuration() < $value);
+						case self::$OPERATION_GT :
+							return ($interval->getDuration() > $value);
+						case self::$OPERATION_EQ :
+							return ($interval->getDuration() != $value);
+						default :
+							return false;
+					}
+				}
+				break;
+			default:
+				return false;
+		}
+	}
+
+	public function loadFromObject($part_obj) {
+		$this->value = 0.;
+		switch ($part_obj->field)
+		{
+			case 'start'        :
+				$this->value = TimeUtils::iso2stamp($part_obj->value);
+				$this->type = self::$TYPE_START;
+				break;
+			case 'stop'         :
+				$this->value = TimeUtils::iso2stamp($part_obj->value);
+				$this->type = self::$TYPE_STOP;
+				break;
+			case 'durationMin'  :
+				$this->value = $part_obj->value;
+				$this->type = self::$TYPE_DURATION_MIN;
+				break;
+			case 'durationHour' :
+				$this->value = $part_obj->value;
+				$this->type = self::$TYPE_DURATION_HOUR;
+				break;
+			case 'durationSec'  :
+				$this->value = $part_obj->value;
+				$this->type = self::$TYPE_DURATION_SEC;
+				break;
+			default:
+				$this->value = 0.;
+				$this->type = self::$TYPE_UNKNOWN;
+		}
+
+		switch ($part_obj->comparison)
+		{
+			case 'lt' :
+				$this->op = self::$OPERATION_LT;
+				break;
+			case 'gt' :
+				$this->op = self::$OPERATION_GT;
+				break;
+			case 'eq' :
+				$this->op = self::$OPERATION_EQ;
+				break;
+			default:
+				$this->op = self::$OPERATION_UNKNOWN;
+		}
+	}
+
+	public function writeBin($handle) {
+		fwrite($handle,pack('L2',$this->type,$this->op));
+		fwrite($handle,pack('f',$this->value));
+	}
+
+	public function loadBin($handle) {
+		$res = unpack('L2data',fread($handle,4*2));
+		$this->type = $res['data1'];
+		$this->op   = $res['data2'];
+
+		$res = unpack('fvalue',fread($handle,4));
+		$this->value = $res['value'];
+	}
+
+	public function dump() {
+		echo "   => TimeTableCacheFilterPartObject : type = ";
+		switch ($this->type)
+		{
+			case self::$TYPE_START :
+				echo "start";
+				break;
+			case self::$TYPE_STOP :
+				echo "stop";
+				break;
+			case self::$TYPE_DURATION_SEC :
+				echo "duration seconde";
+				break;
+			case self::$TYPE_DURATION_MIN :
+				echo "duration minute";
+				break;
+			case self::$TYPE_DURATION_HOUR :
+				echo "duration hour";
+				break;
+			default:
+				echo "unknown";
+		}
+		echo ", operation = ";
+		switch ($this->op)
+		{
+			case self::$OPERATION_LT :
+				echo "lt";
+				break;
+			case self::$OPERATION_GT :
+				echo "gt";
+				break;
+			case self::$OPERATION_EQ :
+				echo "eq";
+				break;
+			default:
+				echo "unknown";
+		}
+		echo ", value = ".$this->value.PHP_EOL;
+	}
+}
+
+class TimeTableCacheFilterObject
+{
+	protected $parts = array();
+
+	function __construct() {
+
+	}
+
+	public function getParts() {
+		return $this->parts;
+	}
+
+	public function reset() {
+		$this->parts = array();
+	}
+
+	public function isEmpty() {
+		return (count($this->parts) == 0);
+	}
+
+	public function loadFromJSON($filter_json) {
+		$this->reset();
+		$filter_obj = json_decode($filter_json);
+
+		foreach ($filter_obj as $filter_part)
+		{
+			$part = new TimeTableCacheFilterPartObject();
+			$part->loadFromObject($filter_part);
+			array_push($this->parts, $part);
+		}
+	}
+
+	public function isSame($filter) {
+		if (count($this->parts) != count($filter->getParts()))
+			return false;
+
+		$identique = true;
+		for ($i = 0; $i < count($this->parts); ++$i)
+		{
+			if (!$this->parts[$i]->isSame($filter->getParts()[$i]))
+			{
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	public function isSameFromJSON($filter_json) {
+		$filter = new TimeTableCacheFilterObject();
+		$filter->loadFromJSON($filter_json);
+		return $this->isSame($filter);
+	}
+
+	public function toFiltered($interval) {
+		foreach ($this->parts as $part)
+		{
+			if ($part->toFiltered($interval))
+				return true;
+		}
+		return false;
+	}
+
+	public function writeBin($handle) {
+		fwrite($handle,pack('L',count($this->parts)));
+		foreach ($this->parts as $part)
+			$part->writeBin($handle);
+	}
+
+	public function loadBin($handle) {
+		$this->reset();
+		$res = unpack('Lcount',fread($handle,4));
+		for ($i = 0; $i < $res['count']; ++$i)
+		{
+			$part = new TimeTableCacheFilterPartObject();
+			$part->loadBin($handle);
+			array_push($this->parts, $part);
+		}
+	}
+
+	public function dump() {
+		echo " => TimeTableCacheFilterObject : number of parts = ".count($this->parts).PHP_EOL;
+		foreach ($this->parts as $part)
+			$part->dump();
+	}
+}
+
+ ?>
diff --git a/php/classes/TimeTableCacheIntervalObject.php b/php/classes/TimeTableCacheIntervalObject.php
new file mode 100644
index 0000000..decd600
--- /dev/null
+++ b/php/classes/TimeTableCacheIntervalObject.php
@@ -0,0 +1,114 @@
+<?php
+class TimeTableCacheIntervalObject
+{
+	protected $id         = -1;
+	protected $index      = -1;
+	protected $start      = 0;
+	protected $stop       = 0;
+	protected $isNew      = false;
+	protected $isModified = false;
+
+	function __construct($id, $index = -1) {
+		$this->id = $id;
+		$this->index = $index;
+	}
+
+	public function getId() {
+		return $this->id;
+	}
+
+	public function getIndex() {
+		return $this->index;
+	}
+
+	public function setIndex($index) {
+		$this->index = $index;
+	}
+
+	public function getStartToStamp() {
+		return $this->start;
+	}
+
+	public function getStartToISO() {
+		return TimeUtils::stamp2iso($this->start);
+	}
+
+	public function setStartFromStamp($stamp) {
+		$this->start = $stamp;
+	}
+
+	public function setStartFromISO($iso) {
+		$this->start = TimeUtils::iso2stamp($iso);
+	}
+
+	public function getStopToStamp() {
+		return $this->stop;
+	}
+
+	public function getStopToISO() {
+		return TimeUtils::stamp2iso($this->stop);
+	}
+
+	public function setStopFromStamp($stamp) {
+		$this->stop = $stamp;
+	}
+
+	public function setStopFromISO($iso) {
+		$this->stop = TimeUtils::iso2stamp($iso);
+	}
+
+	public function getDuration() {
+		return ($this->stop-$this->start);
+	}
+
+	public function isModified() {
+		return $this->isModified;
+	}
+
+	public function setIsModified($isModified) {
+		$this->isModified = $isModified;
+	}
+
+	public function isNew() {
+		return $this->isNew;
+	}
+
+	public function setIsNew($isNew) {
+		$this->isNew = $isNew;
+	}
+
+	public function toArray() {
+		$result = array(
+			"cacheId" => $this->id,
+			"start"   => $this->getStartToISO(),
+			"stop"    => $this->getStopToISO()
+		);
+		if ($this->isNew)
+			$result["isNew"] = true;
+		if ($this->isModified)
+			$result["isModified"] = true;
+
+		return $result;
+	}
+
+
+
+	public function writeBin($handle) {
+		fwrite($handle,pack('L6',$this->id,$this->index,$this->start,$this->stop,$this->isNew,$this->isModified));
+	}
+
+	public function loadBin($handle) {
+		$array = unpack('L6int',fread($handle,6*4));
+		$this->id         = $array['int1'];
+		$this->index      = $array['int2'];
+		$this->start      = $array['int3'];
+		$this->stop       = $array['int4'];
+		$this->isNew      = $array['int5'];
+		$this->isModified = $array['int6'];
+	}
+
+	public function dump() {
+		echo " => Interval : id = ".$this->id.", index = ".$this->index.", start = ".$this->start.", stop = ".$this->stop.", isNew = ".$this->isNew.", isModified = ".$this->isModified.PHP_EOL;
+	}
+}
+?>
diff --git a/php/classes/TimeTableCacheObject.php b/php/classes/TimeTableCacheObject.php
index d2fb579..5960d0d 100644
--- a/php/classes/TimeTableCacheObject.php
+++ b/php/classes/TimeTableCacheObject.php
@@ -4,24 +4,24 @@ class TimeTableCacheObject
 {
 	protected static $format_version = 1;
 	protected static $token_len = 8;
-	
+
 	protected $token  = "";
-	
+
 	protected $lastId = 0;
-	
+
 	protected $intervals = array();
 	protected $indexes   = array();
-	
+
 	protected $isModified = false;
-	
+
 	protected $filter = null;
-	
+
 	protected $sort = null;
 
 	function __construct() {
 		$this->token  = $this->getRandomToken();
-		$this->filter = new FilterCacheObject();
-		$this->sort   = new SortCacheObject();
+		$this->filter = new TimeTableCacheFilterObject();
+		$this->sort   = new TimeTableCacheSortObject();
 	}
 
 	public function reset() {
@@ -30,17 +30,17 @@ class TimeTableCacheObject
 		$this->intervals = array();
 		$this->indexes   = array();
 		unset($this->filter);
-		$this->filter = new FilterCacheObject();;
+		$this->filter = new TimeTableCacheFilterObject();;
 		unset($this->sort);
-		$this->sort = new SortCacheObject();
+		$this->sort = new TimeTableCacheSortObject();
 	}
-	
+
 	public function setIsModified($isModified) {
 		$this->isModified = $isModified;
 	}
-	
+
 	public function addInterval($startIso, $stopIso, $isNew = false, $index = -1) {
-		$interval = new IntervalCacheObject($this->lastId, count($this->intervals));
+		$interval = new TimeTableCacheIntervalObject($this->lastId, count($this->intervals));
 		++$this->lastId;
 		$interval->setStartFromISO($startIso);
 		$interval->setStopFromISO($stopIso);
@@ -54,7 +54,7 @@ class TimeTableCacheObject
 			$this->isModified = true;
 		return $interval;
 	}
-	
+
 	public function removeIntervalFromId($id) {
 		for ($i = 0; $i < count($this->intervals); ++$i)
 		{
@@ -81,10 +81,10 @@ class TimeTableCacheObject
 				return true;
 			}
 		}
-		
+
 		return false;
 	}
-	
+
 	public function modifyIntervalFromId($id, $start, $stop) {
 		foreach ($this->intervals as $interval)
 		{
@@ -99,46 +99,46 @@ class TimeTableCacheObject
 				return true;
 			}
 		}
-		
+
 		return false;
 	}
-	
+
 	public function operationIntervals($extendTime, $shiftTime) {
 		if (($extendTime == 0) && ($shiftTime == 0))
 			//Nothing to do
 			return true;
-		
+
 		for ($i = 0; $i < count($this->indexes); ++$i) {
 			$start = $this->intervals[$this->indexes[$i]]->getStartToStamp();
 			$start -= $extendTime;
 			$start += $shiftTime;
 			$this->intervals[$this->indexes[$i]]->setStartFromStamp($start);
-			
+
 			$stop = $this->intervals[$this->indexes[$i]]->getStopToStamp();
 			$stop += $extendTime;
 			$stop += $shiftTime;
 			$this->intervals[$this->indexes[$i]]->setStopFromStamp($stop);
-			
+
 			$this->intervals[$this->indexes[$i]]->setIsModified(true);
 			$this->isModified = true;
 		}
-		
+
 		return true;
 	}
-	
+
 	public function mergeIntervals() {
 		$this->sort->reset();
-		
+
 		$this->sort->loadFromObject(
 			array(
 				(object)array("property" => "start", "direction" => "DESC")
-			)	
+			)
 		);
-		
+
 		$this->updateIndexes();
-		
+
 		$merged_intervals = array();
-		
+
 		for ($i = 0; $i < count($this->indexes); ++$i) {
 			if (count($merged_intervals) == 0)
 			{
@@ -162,11 +162,11 @@ class TimeTableCacheObject
 					"mod"   => FALSE)
 				);
 		}
-		
+
 		$this->reset();
-		
+
 		foreach ($merged_intervals as $merged_interval) {
-			$interval = new IntervalCacheObject($this->lastId, count($this->intervals));
+			$interval = new TimeTableCacheIntervalObject($this->lastId, count($this->intervals));
 			++$this->lastId;
 			$interval->setStartFromStamp($merged_interval["start"]);
 			$interval->setStopFromStamp($merged_interval["stop"]);
@@ -176,10 +176,10 @@ class TimeTableCacheObject
 			array_push($this->intervals, $interval);
 			array_push($this->indexes, count($this->intervals) - 1);
 		}
-		
+
 		return true;
 	}
-	
+
 	public function getStatistics() {
 		$minTime  = NULL;
 		$maxTime  = NULL;
@@ -187,38 +187,38 @@ class TimeTableCacheObject
 		$maxDuration  = NULL;
 		$indexMinDuration = -1;
 		$indexMaxDuration = -1;
-		
+
 		$nbValid = 0;
 		$durationTotal = 0;
-		
+
 		//Min & Max
 		for ($i = 0; $i < count($this->indexes); ++$i) {
 			if ($this->intervals[$this->indexes[$i]]->getDuration() <= 0)
 				//Invalid interval
 				continue;
-			
+
 			++$nbValid;
 			$durationTotal += $this->intervals[$this->indexes[$i]]->getDuration();
-			
+
 			if (!isset($minTime) || ($minTime > $this->intervals[$this->indexes[$i]]->getStartToStamp()))
 				$minTime = $this->intervals[$this->indexes[$i]]->getStartToStamp();
-			
+
 			if (!isset($maxTime) || ($maxTime < $this->intervals[$this->indexes[$i]]->getStopToStamp()))
 				$maxTime = $this->intervals[$this->indexes[$i]]->getStopToStamp();
-			
+
 			if (!isset($minDuration) || ($minDuration > $this->intervals[$this->indexes[$i]]->getDuration()))
 			{
 				$minDuration      = $this->intervals[$this->indexes[$i]]->getDuration();
 				$indexMinDuration = $i;
 			}
-			
+
 			if (!isset($maxDuration) || ($maxDuration < $this->intervals[$this->indexes[$i]]->getDuration()))
 			{
 				$maxDuration      = $this->intervals[$this->indexes[$i]]->getDuration();
 				$indexMaxDuration = $i;
 			}
 		}
-		
+
 		if (!isset($minTime))
 			$minTime = 0;
 		if (!isset($maxTime))
@@ -227,21 +227,21 @@ class TimeTableCacheObject
 			$minDuration = 0;
 		if (!isset($maxDuration))
 			$maxDuration = 0;
-		
-		
+
+
 		//Mean
 		if ($nbValid > 0)
 			$mean = $durationTotal / $nbValid;
 		else
 			$mean = 0;
-		
+
 		//Standard deviation
 		$pow = 0;
 		for ($i = 0; $i < count($this->indexes); ++$i) {
 			if ($this->intervals[$this->indexes[$i]]->getDuration() <= 0)
 				//Invalid interval
 				continue;
-			
+
 			$pow += pow($this->intervals[$this->indexes[$i]]->getDuration()-$mean,2);
 		}
 		if ($nbValid > 0)
@@ -249,27 +249,27 @@ class TimeTableCacheObject
 		else
 			$variance = 0;
 		$stdev = sqrt($variance);
-		
+
 		//Sort by duration to get median
 		$this->sort->reset();
-		
+
 		$this->sort->loadFromObject(
 				array(
 						(object)array("property" => "durationSec", "direction" => "DESC")
 				)
 		);
-		
+
 		$this->updateIndexes();
-		
+
 		$durations = array();
 		for ($i = 0; $i < count($this->indexes); ++$i) {
 			if ($this->intervals[$this->indexes[$i]]->getDuration() <= 0)
 				//Invalid interval
 				continue;
-			
+
 			array_push($durations, $this->intervals[$this->indexes[$i]]->getDuration());
 		}
-		
+
 		if (count($durations) > 0)
 		{
 			if (count($durations)%2 > 0) {
@@ -280,24 +280,24 @@ class TimeTableCacheObject
 		}
 		else
 			$median = 0;
-		
+
 		//Merge intervals to get density
 		$this->mergeIntervals();
-		
+
 		$durationMergedTotal = 0;
 		for ($i = 0; $i < count($this->indexes); ++$i) {
 			if ($this->intervals[$this->indexes[$i]]->getDuration() <= 0)
 				//Invalid interval
 				continue;
-				
+
 			$durationMergedTotal += $this->intervals[$this->indexes[$i]]->getDuration();
 		}
-		
+
 		if (($maxTime-$minTime) > 0)
 			$density = (($durationMergedTotal/($maxTime-$minTime)));
 		else
 			$density = 0;
-		
+
 		return array(
 			"minDuration"     => $minDuration,
 			"minDurationIndex"=> $indexMinDuration,
@@ -308,10 +308,10 @@ class TimeTableCacheObject
 			"median"  => $median,
 			"density" => $density);
 	}
-	
+
 	public function getStatus() {
 		$nbFiltered = count($this->intervals) - count($this->indexes);
-		
+
 		$nbModified = 0;
 		$nbNew      = 0;
 		$nbInvalid  = 0;
@@ -326,7 +326,7 @@ class TimeTableCacheObject
 			if ($this->intervals[$this->indexes[$i]]->isNew())
 				++$nbNew;
 		}
-		
+
 		return array(
 			"nbFiltered" => $nbFiltered,
 			"nbModified" => $nbModified,
@@ -336,16 +336,16 @@ class TimeTableCacheObject
 			"isModified" => $this->isModified
 		);
 	}
-	
+
 	public function getIntervalsArray($startIndex, $limit,$skipInvalid = false) {
 		$intervals = array();
-		
+
 		if (!isset($startIndex))
 			$startIndex = 0;
-		
+
 		if (!isset($limit))
 			$limit = count($this->indexes);
-		
+
 		for ($i = 0; $i < $limit; ++$i) {
 			if ($startIndex+$i >= count($this->indexes))
 				break;
@@ -355,32 +355,32 @@ class TimeTableCacheObject
 		}
 		return $intervals;
 	}
-	
+
 	public function getLength() {
 		return count($this->indexes);
 	}
-	
+
 	public function getToken() {
 		return $this->token;
 	}
-	
+
 	public function getFilter() {
 		return $this->filter;
 	}
-	
+
 	public function getSort() {
 		return $this->sort;
 	}
-	
+
 	public function updateIndexes() {
 		$this->indexes = array();
-		
+
 		for ($i = 0; $i < count($this->intervals); ++$i)
 			$this->intervals[$i]->setIndex($i);
-		
+
 		//Apply sort
 		$sort_result = $this->sort->apply($this->intervals);
-		
+
 		//Apply filter
 		for ($i = 0; $i < count($sort_result); ++$i)
 		{
@@ -388,24 +388,24 @@ class TimeTableCacheObject
 				array_push($this->indexes,$this->intervals[$sort_result[$i]]->getIndex());
 		}
 	}
-	
+
 	public function writeBin($handle) {
 		//Magic key ("TTC")
 		fwrite($handle,pack('C3',ord('T'),ord('T'),ord('C')));
-		
+
 		//Version
 		fwrite($handle,pack('L',TimeTableCacheObject::$format_version));
-		
+
 		//Token
 		for ($i = 0; $i < TimeTableCacheObject::$token_len; ++$i)
 			fwrite($handle,pack('C',ord($this->token[$i])));
-		
+
 		//Modified
 		fwrite($handle,pack('L',$this->isModified));
-		
+
 		//Filter
 		$this->filter->writeBin($handle);
-		
+
 		//Sort
 		$this->sort->writeBin($handle);
 
@@ -413,21 +413,21 @@ class TimeTableCacheObject
 		fwrite($handle,pack('L2',count($this->intervals), $this->lastId));
 		foreach($this->intervals as $interval)
 			$interval->writeBin($handle);
-		
+
 		//Indexes
 		fwrite($handle,pack('L',count($this->indexes)));
 		foreach($this->indexes as $index)
 			fwrite($handle,pack('L',$index));
 	}
-	
+
 	public function loadBin($handle) {
 		//Magic key ("TTC")
 		if (!$res = unpack('C3key',fread($handle,3)))
 			return false;
-		
+
 		if (($res['key1'] != ord('T')) || ($res['key2'] != ord('T')) || ($res['key3'] != ord('C')))
 			return false;
-		
+
 		//Version
 		if (!$res = unpack('Lversion',fread($handle,4)))
 			return false;
@@ -443,29 +443,29 @@ class TimeTableCacheObject
 			$token .= chr($res['token']);
 		}
 		$this->token = $token;
-		
+
 		//Modified
 		if (!$res = unpack('Lmodified',fread($handle,4)))
 			return false;
 		$this->isModified = $res['modified'];
-		
+
 		//Filter
 		$this->filter->loadBin($handle);
-		
+
 		//Sort
 		$this->sort->loadBin($handle);
-		
+
 		//Intervals
 		$res = unpack('L2data',fread($handle,2*4));
 		$nbIntervals  = $res['data1'];
 		$this->lastId = $res['data2'];
 		for ($i = 0; $i < $nbIntervals; ++$i)
 		{
-			$interval = new IntervalCacheObject(-1);
+			$interval = new TimeTableCacheIntervalObject(-1);
 			$interval->loadBin($handle);
 			array_push($this->intervals, $interval);
 		}
-		
+
 		//Indexes
 		$res = unpack('Ldata',fread($handle,4));
 		$nbIndexes  = $res['data'];
@@ -474,29 +474,29 @@ class TimeTableCacheObject
 			$res = unpack('Lindex',fread($handle,4));
 			array_push($this->indexes, $res['index']);
 		}
-		
+
 		return true;
 	}
-	
+
 	protected function getRandomToken() {
 		$letters = 'abcefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
 		return substr(str_shuffle($letters), 0, TimeTableCacheObject::$token_len);
 	}
-	
+
 	public function dump() {
 		echo " => TimeTableCacheObject : token = ".$this->token.", nb intervals = ".count($this->intervals).", last id = ".$this->lastId.", nb indexes = ".count($this->indexes).PHP_EOL;
 		echo PHP_EOL;
-		
+
 		$this->filter->dump();
 		echo PHP_EOL;
-		
+
 		$this->sort->dump();
 		echo PHP_EOL;
-		
+
 		foreach ($this->intervals as $interval)
 			$interval->dump();
 		echo PHP_EOL;
-		
+
 		echo " => Indexes list : ";
 		foreach ($this->indexes as $index)
 		{
@@ -506,4 +506,4 @@ class TimeTableCacheObject
 	}
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/php/classes/TimeTableCacheSortObject.php b/php/classes/TimeTableCacheSortObject.php
new file mode 100644
index 0000000..60de5c3
--- /dev/null
+++ b/php/classes/TimeTableCacheSortObject.php
@@ -0,0 +1,261 @@
+<?php
+
+class TimeTableCacheSortPartObject
+{
+	public static $TYPE_UNKNOWN       = 0;
+	public static $TYPE_START         = 1;
+	public static $TYPE_STOP          = 2;
+	public static $TYPE_DURATION_SEC  = 3;
+	public static $TYPE_DURATION_MIN  = 4;
+	public static $TYPE_DURATION_HOUR = 5;
+
+	public static $DIRECTION_UNKNOWN = 0;
+	public static $DIRECTION_ASC     = 1;
+	public static $DIRECTION_DES     = 2;
+
+	protected $type;
+	protected $dir;
+
+	function __construct() {
+		$this->type = self::$TYPE_UNKNOWN;
+		$this->dir  = self::$DIRECTION_UNKNOWN;
+	}
+
+	public function getType() {
+		return $this->type;
+	}
+
+	public function getDir() {
+		return $this->dir;
+	}
+
+	public function isSame($part) {
+		return (($this->type == $part->getType()) && ($this->dir == $part->getDir()));
+	}
+
+	public function compare($interval_a, $interval_b) {
+		switch ($this->type) {
+			case self::$TYPE_START :
+				{
+					switch ($this->dir) {
+						case self::$DIRECTION_ASC :
+							return ($interval_b->getStartToStamp() - $interval_a->getStartToStamp());
+						default :
+							return ($interval_a->getStartToStamp() - $interval_b->getStartToStamp());
+					}
+				}
+				break;
+			case self::$TYPE_STOP :
+				{
+					switch ($this->dir) {
+						case self::$DIRECTION_ASC :
+							return ($interval_b->getStopToStamp() - $interval_a->getStopToStamp());
+						default :
+							return ($interval_a->getStopToStamp() - $interval_b->getStopToStamp());
+					}
+				}
+				break;
+			case self::$TYPE_DURATION_SEC :
+			case self::$TYPE_DURATION_MIN :
+			case self::$TYPE_DURATION_HOUR :
+				{
+					switch ($this->dir) {
+						case self::$DIRECTION_ASC :
+							return ($interval_b->getDuration() - $interval_a->getDuration());
+						default :
+							return ($interval_a->getDuration() - $interval_b->getDuration());
+					}
+				}
+				break;
+			default :
+				return 0;
+		}
+		return 0;
+	}
+
+	public function loadFromObject($part_obj) {
+		switch ($part_obj->property)
+		{
+			case 'start'        :
+				$this->type = self::$TYPE_START;
+				break;
+			case 'stop'         :
+				$this->type = self::$TYPE_STOP;
+				break;
+			case 'durationMin'  :
+				$this->type = self::$TYPE_DURATION_MIN;
+				break;
+			case 'durationHour' :
+				$this->type = self::$TYPE_DURATION_HOUR;
+				break;
+			case 'durationSec'  :
+				$this->type = self::$TYPE_DURATION_SEC;
+				break;
+			default:
+				$this->type = self::$TYPE_UNKNOWN;
+		}
+
+		switch ($part_obj->direction)
+		{
+			case 'ASC' :
+				$this->dir = self::$DIRECTION_ASC;
+				break;
+			case 'DESC' :
+				$this->dir = self::$DIRECTION_DES;
+				break;
+			default:
+				$this->dir = self::$DIRECTION_UNKNOWN;
+		}
+	}
+
+	public function writeBin($handle) {
+		fwrite($handle,pack('L2',$this->type,$this->dir));
+	}
+
+	public function loadBin($handle) {
+		$res = unpack('L2data',fread($handle,4*2));
+		$this->type = $res['data1'];
+		$this->dir   = $res['data2'];
+	}
+
+	public function dump() {
+		echo "   => TimeTableCacheSortPartObject : type = ";
+		switch ($this->type)
+		{
+			case self::$TYPE_START :
+				echo "start";
+				break;
+			case self::$TYPE_STOP :
+				echo "stop";
+				break;
+			case self::$TYPE_DURATION_SEC :
+				echo "duration seconde";
+				break;
+			case self::$TYPE_DURATION_MIN :
+				echo "duration minute";
+				break;
+			case self::$TYPE_DURATION_HOUR :
+				echo "duration hour";
+				break;
+			default:
+				echo "unknown";
+		}
+		echo ", direction = ";
+		switch ($this->dir)
+		{
+			case self::$DIRECTION_ASC :
+				echo "ASC";
+				break;
+			case self::$DIRECTION_DES :
+				echo "DESC";
+				break;
+			default:
+				echo "unknown";
+		}
+		echo PHP_EOL;
+	}
+}
+
+class TimeTableCacheSortObject
+{
+	protected $parts = array();
+
+	function __construct() {
+	}
+
+	public function getParts() {
+		return $this->parts;
+	}
+
+	public function reset() {
+		$this->parts = array();
+	}
+
+	public function isEmpty() {
+		return (count($this->parts) == 0);
+	}
+
+	public function loadFromObject($sort_obj) {
+		$this->reset();
+		foreach ($sort_obj as $sort_part)
+		{
+			$part = new TimeTableCacheSortPartObject();
+			$part->loadFromObject($sort_part);
+			array_push($this->parts, $part);
+		}
+	}
+
+	public function isSameFromObject($sort_obj) {
+		$sort = new TimeTableCacheSortObject();
+		$sort->loadFromObject($sort_obj);
+		return $this->isSame($sort);
+	}
+
+	public function isSame($sort) {
+		if (count($this->parts) != count($sort->getParts()))
+			return false;
+
+		$identique = true;
+		for ($i = 0; $i < count($this->parts); ++$i)
+		{
+			if (!$this->parts[$i]->isSame($sort->getParts()[$i]))
+			{
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	public function apply($intervals) {
+		$sorted_indexes = array();
+
+		global $global_parts, $global_intervals;
+		$global_parts = $this->parts;
+		$global_intervals = $intervals;
+
+		foreach ($intervals as $interval)
+			array_push($sorted_indexes, $interval->getIndex());
+
+		if (count($global_parts) == 0)
+			return $sorted_indexes;
+
+		usort($sorted_indexes, function ($index_a, $index_b) {
+			global $global_parts, $global_intervals;
+			foreach ($global_parts as $part)
+			{
+				$res = $part->compare($global_intervals[$index_a], $global_intervals[$index_b]);
+				if ($res != 0)
+					return $res;
+			}
+			return $index_a-$index_b;
+		});
+
+		return $sorted_indexes;
+	}
+
+	public function writeBin($handle) {
+		fwrite($handle,pack('L',count($this->parts)));
+		foreach ($this->parts as $part)
+			$part->writeBin($handle);
+	}
+
+	public function loadBin($handle) {
+		$this->reset();
+		$res = unpack('Lcount',fread($handle,4));
+		for ($i = 0; $i < $res['count']; ++$i)
+		{
+			$part = new TimeTableCacheSortPartObject();
+			$part->loadBin($handle);
+			array_push($this->parts, $part);
+		}
+	}
+
+	public function dump() {
+		echo " => TimeTableCacheSortObject : number of parts = ".count($this->parts).PHP_EOL;
+		foreach ($this->parts as $part)
+			$part->dump();
+	}
+}
+
+ ?>
--
libgit2 0.21.2