Location: PHPKode > scripts > dList v3 > dlist/dList.php
<?
//dList v3  16. September 2003

//Martin Langecker 
//hide@address.com

//Very useful object list (like ArrayList in .net) extended with mysql db functions

//UPDATES IN V3 !!!!!
//Now you are able to automatically generate an edit form for a string list
//Save the changes of the edit form
//Call a function for every object in the list

//UPDATES IN V2 !!!!!
//Eliminated some Bugs
//Now there are two modes (DB,MEMORY)
//		DB mode to work directly to the db (without caching data)
//		MEMORY to work fast (but you must have more memory)
//Now the whole list automatically serializes to the DB with the Save command
//Now the whole list automatically unserializes from Db with the Load command
//Ability to Save several Lists to one Table with the ListIdentifyer
//Ability to autocreate the Table in the Db

//I tried to write the class compatible to php v5 (or Zend 2.0). But I am not able to try it!

class dList
{
	//Constants
	var $UNLIMITEDCAPACITY ="{unlimited capacity}";
	var $NOOBJECT="{no object}";
	var $EMPTY="{empty}";
	var $NULL="{NULL}";
	var $DB="{DB}";
	var $MEMORY="{MEMORY}";
	var $ONLYSTRINGS="1";
	
	//standard Variables
	var $objectCount;    	//number of items in the list
	var $capacity; 			//the capacity of the list
	var $objectList;     	//the list itself

	//variables for Db functions
	var $sqlServer;         //the Sql Server and Port ("localhost:3306")
	var $sqlUser;			//the Sql User
	var $sqlPw;				//the Sql password
	var $sqlDb;				//the Sql database name
	var $sqlTable;			//the name of the table to write
	var $listIdentifyer;    //Identifies the objects of the list in a Table
	var $dbAvailable;       //A bool if Database functions are available
	var $mode;				//DB or MEMORY Mode

	//Constructor
	function dList()
	{
		$this->mode=$this->MEMORY;
		$this->Clear();
		$this->capacity=$this->UNLIMITEDCAPACITY;
		$this->sqlServer=$this->EMPTY;
		$this->sqlUser=$this->EMPTY;
		$this->sqlPw=$this->EMPTY;
		$this->sqlDb=$this->EMPTY;
		$this->sqlTable=$this->EMPTY;
		$this->listIdentifyer=$this->EMPTY;
		$this->dbAvailable=false;
	}	

	//Basic functions

	//Add an Object to the list.
	//Returns bool=true if successful
	function Add($object)
	{ 
		if(($this->capacity==$this->UNLIMITEDCAPACITY) || ($this->capacity > $this->objectCount))
		{ 
			if($this->mode==$this->MEMORY)
			{ 
				$this->objectList[$this->objectCount]=$object;
				$this->objectCount++;
				return true;
			}
			elseif($this->mode==$this->DB)
			{
				if($this->dbAvailable==true)
				{ 	
					$link=$this->connect();
					if($link!=false)
					{
						mysql_db_query($this->sqlDb,"insert into ".$this->sqlTable." (`ListIdentifyer`, `ListIndex`, `ListObject`) VALUES ('".$this->listIdentifyer."','".$this->objectCount."','".serialize($object)."');",$link);
						mysql_db_query($this->sqlDb,"Commit;",$link);
						echo mysql_error();
						$this->objectCount++;
						mysql_close($link);
						return true;
					}
				}
			}
		}
		return false;
	}
	
	//Call the function of every Object in the list
	//returns true
	function Call($delegateFunction)
	{
		if($delegateFunction!="")
		{
			for($i=0; $i<$this->objectCount; $i++)
			{
				if(is_object($this->objectList[$i]))
				{
					$this->objectList[$i]->$delegateFunction();
				}
			}
			return true;
		}
		else return false;
	}
	
	//Clear the whole list.
	//returns bool=true if successful
	function Clear()
	{
		if($this->mode==$this->MEMORY)
		{
			$this->objectCount=0;
			$this->objectList[0]=$this->EMPTY;
		}
		elseif($this->mode==$this->DB)
		{
			$link=$this->Connect();
			if($link!=false)
			{
				$this->ClearDB($link);
				mysql_close($link);
			}
			return false;
		}
		return true;
	}
	
	//Clears the Database entries of this list.
	//returns bool=true if successful
	function ClearDB($link)
	{
		$this->objectCount=0;
		mysql_db_query($this->sqlDb,"delete from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."';",$link);
		echo mysql_error();
		mysql_db_query($this->sqlDb,"Commit;",$link);
		return true;
	}
	
	//Get the number of objects in the list
	//returns an int
	function Count()
	{
		return $this->objectCount;
	}

	//Check if the List contains the Object
	//Returns bool=true if successful
	function Contains($object)
	{
		if($this->mode==$this->MEMORY)
		{
			for($i=0; $i<$this->objectCount; $i++)
			{
				if($this->objectList[$i] == $object)
					return true;
			}
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				$link=$this->Connect();
				if($link!=false)
				{
					$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListObject='".serialize($object)."';",$link);
					echo mysql_error();
					if(mysql_num_rows($result)>0)
					{	
						mysql_close($link);
						return true;
					}
					mysql_close($link);
				}
				return false;
			}
		}
		return false;
	}
	
	//Connects to the Database
	//returns a link identyfyer or false
	function Connect()
	{
		if($this->dbAvailable==true)
		{
			$link=mysql_connect($this->sqlServer,$this->sqlUser,$this->sqlPw);
			return $link;
		}
		return false;
	}

	//Creates a new Identification
	//returns true or false
	function CreateIdentity()
	{
		if($this->dbAvailable==true)
		{
			$link=$this->Connect();
			if($link!=false)
			{
				$a=false;
				while($a==false)
				{
					$this->listIdentifyer="list:".rand(0,10000);
					$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer = '".$this->listIdentifyer."';",$link);
					if(mysql_num_rows($result)<=0)
						$a=true;
				}
				mysql_close($link);
				return true;	
			}
		}
		return false;
	}

	//Deletes a single item from the Database
	function DeleteItem($index,$link)
	{
		mysql_db_query($this->sqlDb,"delete from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListIndex='".$index."';",$link);
		mysql_db_query($this->sqlDb,"Commit;",$link);
		echo mysql_error();
	}

	//Echos each object of the List
	//returns true
	function EchoList()
	{
		return $this->EchoList2("");
	}
	
	//Echos each object of the List
	//returns true
	function EchoList2($spacingString)
	{
		if($this->mode==$this->MEMORY)
		{  
			for($i=0; $i<$this->objectCount; $i++)
			{
				echo $this->objectList[$i].$spacingString;
			}	
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				$link=$this->Connect();
				if($link!=false)
				{
					$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' order by ListIndex asc;",$link);
					echo mysql_error();
					if(mysql_num_rows($result)>0)
					{	
						$e=mysql_num_rows($result);
						for($i=0; $i<$e; $i++)
						{
							$row=mysql_fetch_array($result);
							echo unserialize($row["ListObject"]).$spacingString;
						}
					}
					mysql_close($link);
				}
			}
		}
		return true;
	}

	//Edit is a combination of EditString and Call
	//returns true
	function Edit($delegateFunction,$internalList)
	{
		if($this->mode==$this->MEMORY)
		{  
			echo "<form action='$PHP_SELF' method='post'>";
			echo "<table border='0' cellpadding='0' cellspacing='0' bgcolor='#cccccc'><tr><td align='center'>";
			echo "<table border='0' cellpadding='0' cellspacing='0'><tr><td><strong>".$this->GetIdentity()."</strong></td></tr></table></td></tr>";
			for($i=0; $i<$this->objectCount; $i++)
			{
				if(is_string($this->objectList[$i]))
				{
					echo "<tr><td><input type='text' name='$internalList"."[$i]' value='".$this->objectList[$i]."'><br></td></tr>";
				}
				elseif(is_object($this->objectList[$i]))
				{
					echo "<tr><td>";
					$this->objectList[$i]->$delegateFunction();
					echo "</td></tr>";
				}
			}
			echo"<tr><td><input type='submit'></td></tr>";
			echo"</table>";
			echo"</form>";
		}
		elseif($this->mode==$this->DB)
		{
			$this->SwitchToMemoryMode();
			$this->Edit($delegateFunction);
			$this->SwitchToDbMode();
		}
		return true;
	}

	//Edit the list items if they are strings
	//returns true if successfull
	function EditStrings($internalList)
	{
		return $this->RecursiveEdit2($internalList,"",0,$this->ONLYSTRINGS);
	}
	
	//Get the Capacity of the list
	//returns an int or Capacity unlimited
	function GetCapacity()
	{
		return $this->capacity;
	}

	//returns the Object at that index
	//returns an object
	function Get($index)
	{
		if($this->mode==$this->MEMORY)
		{
			if($index >= $this->objectCount) 
				return $this->NULL;
			else
				return $this->objectList[$index];
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				$link=$this->Connect();
				if($link!=false)
				{
					$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListIndex='".$index."';",$link);
					echo mysql_error();
					if(mysql_num_rows($result)>0)
					{
						$row=mysql_fetch_array($result);
						return unserialize($row["ListObject"]);
					}
					mysql_close($link);
				}
				return $this->NULL;
			}
		}
	}

	//Get the Identification String of the List (is unique) ONLY USED WITH DB FEATURES
	//returns a string or false
	function GetIdentity()
	{
		if($this->listIdentifyer!=$this->EMPTY)
			return $this->listIdentifyer;
		else 
			return false;
	}
	
	//Returns the mode of the List (Db or Memory)
	function GetMode()
	{
		return $this->mode;
	}
	
	//Get only a part of the List
	//returns a dList
	function GetRange($startIndex,$endIndex)
	{	
		$selectedRangeOfList = new dList();
		if($this->mode==$this->MEMORY)
		{ 
			for($i=$startIndex; $i <= $endIndex; $i++)
			{	
				$selectedRangeOfList->Add($this->objectList[$i]);
			}
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				$link=$this->Connect();
				if($link!=false)
				{
					$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListIndex >='".$startIndex."' and ListIndex <='".$endIndex."' order by ListIndex asc;",$link);
					echo mysql_error();
					if(mysql_num_rows($result)>0)
					{
						$e=mysql_num_rows($result);
						for($i=0;$i<$e;$i++)
						{
							$row=mysql_fetch_array($result);
							$selectedRangeOfList->Add(unserialize($row["ListObject"]));
						}
					}
					mysql_close($link);
				}
			}
		} 
		return $selectedRangeOfList;
	}
	
	//internally used
	//returns an int
	function GetRecursiveDepth($depth)
	{
		if($depth=="")$depth=0;
		for($i=0;$i<$this->objectCount;$i++)
		{
			if(is_object($this->objectList[$i]))
			{ 
				$help=&$this->objectList[$i];
				$help2=$help->GetRecursiveDepth($depth+1);
				if($help2>$depth)
					$depth=$help2;
			}
		}
		return $depth;
	}
	
	//Insert an Object at a special position. 
	//Returns bool=true if successful
	function Insert($object,$index)
	{
		if((($this->capacity!=$this->UNLIMITEDCAPACITY) || ($this->capacity < $this->objectCount)) && ($this->objectCount < $index))
			return false;
		else
		{ 
			if($this->mode==$this->MEMORY)
			{   
				for($i=($this->objectCount-1); $i >= $index; $i--)
				{
					$this->objectList[$i+1]=$this->objectList[$i];
				}
				$this->objectList[$index]=$object;
				$this->objectCount++;
			}
			elseif($this->mode==$this->DB)
			{
				if($this->dbAvailable==true)
				{
					//You will think the following code is not clean
					//but it is much easier and as fast as another solution
					$this->SwitchToMemoryMode();    
					$this->Insert($object,$index);
					$this->SwitchToDbMode();
				}
			}
		}
		return true;
	}

	//Find the Index of an Object
	//Returns an int if successfull, false if failed
	function IndexOf($object)
	{
		if($this->mode==$this->MEMORY)
		{
			for($i=0; $i<$this->objectCount; $i++)
			{
				if($this->objectList[$i] == $object)
					return $i;
			}
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				$link=$this->Connect();
				if($link!=false)
				{
					$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListObject='".serialize($object)."';",$link);
					echo mysql_error();
					if(mysql_num_rows($result)>0)
					{
						$row=mysql_fetch_array($result);
						return $row["ListIndex"];
					}
					mysql_close($link);
				}
			}
		}
		return false;
	}

	//Checks if this item exists in the Database
	function ItemExistsInDb($index,$link)
	{
		$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListIndex='".$index."';",$link);
		echo mysql_error();
		if(mysql_num_rows($result)>0)
			return true;
		return false;
	}
	
	//Find the last Index of an Object
	//Returns an int if successfull, false if failed
	function LastIndexOf($object)
	{
		if($this->mode==$this->MEMORY)
		{
			for($i=($this->objectCount-1); $i >= 0; $i--)
			{
				if($this->objectList[$i]==$object)
					return $i;
			}
		}
		elseif($this->mode==$this->DB)
		{
			$this->SwitchToMemoryMode();
			$i=$this->LastIndexOf($object);
			$this->SwitchToDbMode();
			return $i;
		}
		return false;
	}

	//Loads the List from the Database
	//returns true if successful
	function Load()
	{
		if($this->mode==$this->DB) //There is nothing to save if you are in the DB mode
			return true;
			
		if($this->dbAvailable)
		{
			$link=$this->Connect();
			if($link!=false)
			{
				$result=mysql_db_query($this->sqlDb,"select * from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."';",$link);
				echo mysql_error();
				if($result!=false)
				{
					$e=mysql_num_rows($result);
					for($i=0;$i<$e;$i++)
					{
						$row=mysql_fetch_array($result);
						$this->objectList[$row["ListIndex"]]=unserialize($row["ListObject"]);
					}
					$this->objectCount=$e;
					mysql_close($link);
					return true;
				}
				mysql_close($link);
			}
		}
		return false;
	}
	
	//Recursive Edits Lists
	//returns true
	function RecursiveEdit($internalList)
	{
		return $this->RecursiveEdit2($internalList,"",0,0);
	}

	//Recursive Edits Lists (internal used)
	//returns true
	function RecursiveEdit2($internalList,$pre,$level,$flag)
	{
		if($this->mode==$this->MEMORY)
		{  
			if($level==0)
				echo"<form action='$PHP_SELF' method='post'>";
				
			echo "<table border='0' cellpadding='0' cellspacing='0' bgcolor='#cccccc'>";
			if($this->GetIdentity()!="")echo "<tr><td align='center'><table border='0' cellpadding='0' cellspacing='0'><tr><td><strong>".$this->GetIdentity()."</strong></td></tr></table></td><td>&nbsp;</td></tr>";
			for($i=0; $i<$this->objectCount; $i++)
			{
				if(is_string($this->objectList[$i]))
				{
					echo "<tr><td><input type='text' name='$internalList"."$pre"."[$i]' value='".$this->objectList[$i]."'></td><td>&nbsp;</td></tr>";
				}
				elseif(is_object($this->objectList[$i])&&($flag!=$this->ONLYSTRINGS))
				{
					echo "<tr><td>&nbsp;</td><td>";
					$this->objectList[$i]->RecursiveEdit2($internalList,$pre."[$i]",$level+1,$flag);
					echo "</td></tr>";
				}
			}
			if($level==0)
				echo "<tr><td colspan='2' align='center'><input type='submit'></td></tr>";
				
			echo"</table>";
			
			if($level==0)
				echo "</form>";
		}
		elseif($this->mode==$this->DB)
		{
			$this->SwitchToMemoryMode();
			$this->Edit($delegateFunction);
			$this->SwitchToDbMode();
		}
		return true;
	}

	//Remove an object from the list
	//Returns bool=true if successful
	function Remove($object)
	{
		if($this->mode==$this->MEMORY)
		{
			while($this->Contains($object))
			{
				for($i = $this->IndexOf($object); $i < ($this->objectCount-2); $i++)
				{
					$this->objectList[$i]=$this->objectList[$i+1];
				}
				$this->objectCount--;
			}
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				//Sql command delete is not faster because we must change the index of the elements
				$this->SwitchToMemoryMode();
				$this->Remove($object);
				$this->SwitchToDbMode();
			}
		}
		return true;
	}

	//Remove an object at the specified index
	//Returns bool=true if successful
	function RemoveAt($index)
	{ 
		if(($index < $this->objectCount) && ($index >= 0))
		{
			if($this->mode==$this->MEMORY)
			{
				for($i = $index; $i < ($this->objectCount-1); $i++)
				{
					$this->objectList[$i]=$this->objectList[$i+1];
				}
				$this->objectCount--;
				return true;
				
			}
			elseif($this->mode==$this->DB)
			{
				if($this->dbAvailable==true)
				{ 
					//Sql command delete is not faster because we must change the index of the elements
					$this->SwitchToMemoryMode();
					$this->RemoveAt($index);
					$this->SwitchToDbMode();
				}
			}
			
		}
		return false;
	}

	//Removes a range of items from the list
	//Returns bool=true if successful
	function RemoveRange($index,$count)
	{
		if(($index+$count) > $this->objectCount)
			return false;
		
		if($this->mode==$this->MEMORY)
		{
			for($i=$index; $i < ($this->objectCount-$count); $i++)
			{
				$this->objectList[$i]=$this->objectList[$i+$count];
			}
			$this->objectCount-=$count;
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				//Sql command delete is not faster because we must change the index of the elements
				$this->SwitchToMemoryMode();
				$this->RemoveRange($index,$count);
				$this->SwitchToDbMode();
			}
		}
		return true;
	}

	//Reverses the List
	//Returns bool=true if successful
	function Reverse()
	{
		if($this->mode==$this->MEMORY)
		{
			for($i=0; $i < ($this->objectCount/2); $i++)
			{
				$object = $this->objectList[$i];
				$this->objectList[$i]=$this->objectList[$this->objectCount-1-$i];
				$this->objectList[$this->objectCount-1-$i]=$object;
			}
		}
		elseif($this->mode==$this->DB)
		{
			if($this->dbAvailable==true)
			{
				//Sql command delete is not faster because we must change the index of the elements
				$this->SwitchToMemoryMode();
				$this->Reverse();
				$this->SwitchToDbMode();
			}
		}
		return true;
	}

	//Saves the List to Db
	//returns true if successfull
	function Save()
	{
		if($this->mode==$this->DB) //there is nothing to load if you are in the db mode
			return true;
	
		if($this->dbAvailable)
		{
			$link=$this->Connect();
			if($link!=false)
			{
				if($this->objectCount > 0)
				{ 
					mysql_db_query($this->sqlDb,"delete from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."' and ListIndex >= ".$this->objectCount.";",$link);
					echo mysql_error();
				}
					
				for($i=0;$i<$this->objectCount;$i++)
				{
					if($this->ItemExistsInDb($i,$link)==true)
						$this->DeleteItem($i,$link);
						
					$this->SaveItem($i,$link);
				}
				mysql_close($link);
				return true;
			}
		}
		return false;
	}

	//Save the changes of EditStrings
	//return true if success
	function SaveEdit($internalList)
	{
		return $this->SaveRecursiveEdit($internalList);
	}

	//Save the changes of EditStrings
	//return true if success
	function SaveEditStrings($internalList)
	{
		return $this->SaveRecursiveEdit($internalList);
	}

	//Save the changes of RecursiveEdit
	//return true if success
	function SaveRecursiveEdit($internalList)
	{
		if(is_array($internalList))
		{
			if($this->mode==$this->MEMORY)
			{	
				foreach($internalList as $key1=>$value1)
				{	
					if(is_array($value1))
					{  	
						$help=&$this->objectList[$key1];
						$help->SaveRecursiveEdit($value1);
					}
					elseif(is_string($value1))
					{	
						$this->objectList[$key1]=$value1;
					}
				}
				return true;
			}
			elseif($this->mode==$this->DB)
			{
				$this->SwitchToMemoryMode();
				$this->SaveEditStrings($internalList);
				$this->SwitchToDbMode();
			}
		}
	}
	
	//Saves a single item to the Database
	function SaveItem($index,$link)
	{
		mysql_db_query($this->sqlDb,"insert into ".$this->sqlTable." (`ListIdentifyer`, `ListIndex`, `ListObject`) VALUES ('".$this->listIdentifyer."','".$index."','".serialize($this->objectList[$index])."');",$link);
		mysql_db_query($this->sqlDb,"Commit;",$link);
		echo mysql_error();
	}
	
	//Sets the Capacity of the List
	//returns true
	function SetCapacity($value)
	{
		$this->capacity=$value;
		return true;
	}
	
	//Set the parameters for DB functions
	//returns true if parameters are correct else a string with the mysql_error
	function SetDbParameters($sqlServer,$sqlUser,$sqlPw,$sqlDb,$sqlTableName,$createTable)
	{
		if(($link=mysql_connect($sqlServer,$sqlUser,$sqlPw))!=false)
		{
			if($createTable==true)
			{ 
				$result=mysql_list_tables($sqlDb,$link);
				$a=false;
				for ($i = 0; $i < mysql_num_rows($result); $i++)
       				if(mysql_tablename($result, $i)==$sqlTableName)
						$a=true;

				if($a==false)
				{
						//create this table
						mysql_db_query($sqlDb," 
													CREATE TABLE `".$sqlTableName."` (
																			`ListIdentifyer` VARCHAR(20) NOT NULL, 
																			`ListIndex` INT(8) NOT NULL, 
																			`ListObject` LONGTEXT NOT NULL,
																			PRIMARY KEY (`ListIdentifyer`, `ListIndex`)
																		 )
							 				",$link);
						mysql_db_query($this->sqlDb,"Commit;",$link);
				}
			}
			$this->sqlServer=$sqlServer;
			$this->sqlUser=$sqlUser;
			$this->sqlPw=$sqlPw;
			$this->sqlDb=$sqlDb;
			$this->sqlTable=$sqlTableName;
			$this->dbAvailable=true;
			mysql_close($link);
			$this->CreateIdentity();
			return true;
		}
		return mysql_error();
	}
	
	//Set the Identification String of a List (must be unique) 
	//returns true on success
	function SetIdentity($identificationString)
	{
		$this->listIdentifyer=$identificationString;
		return true;
	}
	
	//Switches the List to Db Mode
	//return true on success
	function SwitchToDbMode()
	{
		if($this->dbAvailable==false)
			return false;
		
		$this->Save();
		$this->Clear();
		
		$link=$this->Connect();
		if($link==false)
			return false;
		
		$result=mysql_db_query($this->sqlDb,"select count(ListIdentifyer) from ".$this->sqlTable." where ListIdentifyer='".$this->listIdentifyer."';",$link);
		echo mysql_error();
		$row=mysql_fetch_array($result);
		$this->objectCount=$row["count(ListIdentifyer)"];
		
		mysql_close($link);
		$this->mode=$this->DB;
		return true;
	}
	
	//Switches the List to MemoryMode
	//returns true
	function SwitchToMemoryMode()
	{
		$this->mode=$this->MEMORY;
		$this->Clear();
		if($this->dbAvailable==true)
			$this->Load();
		return true;
	}
}
?>
Return current item: dList v3