<?php
global $ItemTypePrefixes;

$ItemTypePrefixes = array();
$ItemTagFiles = array();

function RegisterPrefix($class,$prefix,$file)
{
 	global $ItemTypePrefixes, $ItemTagFiles;
    	
 	$ItemTypePrefixes[$class] = $prefix;
 	$ItemTagFiles[$prefix] = $file;
}

class clsParsedItem extends clsItemDB
{
    var $TagPrefix;
    var $Parser;
    var $AdminParser;    

    function clsParsedItem($id=NULL)
    {
        global $TemplateRoot;

        $this->clsItemDB();
        $this->Parser = new clsTemplateList($TemplateRoot);
        $this->AdminParser = new clsAdminTemplateList();
    }
        
/*    function ParseObject($element)
    {
        $extra_attribs = ExtraAttributes($element->attributes);
        if(strtolower($element->name)==$this->TagPrefix)
        {
            $field = strtolower($element->attributes["_field"]);
            $tag = $this->TagPrefix."_".$field;
            $ret = $this->parsetag($tag);
        }
        return $ret;
    }
*/
	function ParseTimeStamp($d,$attribs=array())
	{
       if( isset($attribs["_tz"]) )
       {
            $d = GetLocalTime($d,$objSession->Get("tz"));
       }
       $part = isset($attribs["_part"]) ? strtolower($attribs["_part"]) : '';
       if(strlen($part))
       {
          $ret = ExtractDatePart($part,$d);
       }
       else
       {
         if($d<=0)
         {
            $ret = "";
         }
         else
            $ret = LangDate($d);
       }		
       return $ret;
	}		
	
	function ParseObject($element)
    {
        global $objConfig, $objCatList, $var_list_update, $var_list, $n_var_list_update, $m_var_list_update;

        $extra_attribs = ExtraAttributes($element->attributes);
        $ret = "";
        
        if ($this->TagPrefix == "email" && strtolower($element->name) == "touser") {
        	$this->TagPrefix = "touser";        	
        }
        
        if(strtolower($element->name)==$this->TagPrefix)
        {
            $field = strtolower($element->attributes["_field"]);
            switch($field)
            {     
				case 'primarycategorylink':
					$m_var_list_update['cat'] = (int)$this->GetPrimaryCategory();
	                $m_var_list_update['p'] = 1;
	                $ret = str_replace('advanced_view.php','browse.php',$_SERVER['PHP_SELF']).'?env='.BuildEnv();
	                unset($m_var_list_update['cat']);
	                unset($m_var_list_update['p']);
	                return $ret;
            		break;
            	
            	case 'primarycategory':
					$db =& GetADODBConnection();
            		$sql = 'SELECT CachedNavbar FROM '.$objCatList->SourceTable.' WHERE CategoryId = '.(int)$this->GetPrimaryCategory();
            		$ret = prompt_language($objConfig->Get("Root_Name"));
            		if( $this->GetPrimaryCategory() ) $ret .= '>'.$db->GetOne($sql); 
            		break;
            	
            	case "id":
            	$ret = $this->Get($this->id_field);
            break;	       	
            case "resourceid":
              if(!$this->NoResourceId)
                $ret = $this->Get("ResourceId");
            break;    
            case "category":
            	$c = $objCatList->GetItem($this->Get("CategoryId"));
                if(is_object($c))
                {
                   $ret = $c->parsetag($element->attributes["_cattag"]);
                }
            break;            
            case "priority":
                if($this->Get("Priority")!=0)
                {               
                    $ret = (int)$this->Get("Priority");
                }
                else
                    $ret = "";
            break;            
            case "link":
            	if(method_exists($this,"ItemURL"))
            	{     
            	  $ret = $this->ItemURL($element->attributes["_template"],FALSE,"");            	  	
            	}
            break;	
            case "cat_link":
            	if(method_exists($this,"ItemURL"))
            	{
            	  $ret = $this->ItemURL($element->attributes["_template"],TRUE,"");            	  	
            	}            
            break;
            case "fullpath":                                  
                $ret = $this->Get("CachedNavbar");
                if(!strlen($ret))
                {
                    if(is_numeric($this->Get("CategoryId")))
                    {
                       $c = $objCatList->GetItem($this->Get("CategoryId"));
                       if(is_object($c))
                         $ret = $c->Get("CachedNavbar");
                    }
                    else
                    {
                    	if(method_exists($this,"GetPrimaryCategory"))
                    	{
                          $cat = $this->GetPrimaryCategory();
                          $c = $objCatList->GetItem($cat);
                          if(is_object($c))
                            $ret = $c->Get("CachedNavbar");
                    	}
                    }
                }
               // $ret = $this->HighlightText($ret);
            break;    
                        
            case "relevance":            
	            $style = $element->attributes["_displaymode"];	            
	            if(!strlen($style))
	              $style = "numerical";
	            switch ($style)
	            {                
	            	case "numerical":	            	
	                	$ret = (100 * LangNumber($this->Get("Relevance"),1))."%";
	                	break;	                	
	                case "bar":                                          	 	                
	                	$OffColor = $element->attributes["_offbackgroundcolor"];
	                	$OnColor = $element->attributes["_onbackgroundcolor"];
	                	$percentsOff = (int)(100 - (100 * $this->Get("Relevance")));	                	if ($percentsOff)
	                	{
		                	$percentsOn = 100 - $percentsOff;
		                	$ret = "<td width=\"$percentsOn%\" bgcolor=\"$OnColor\"><img src=\"img/s.gif\"></td><td width=\"$percentsOff%\" bgcolor=\"$OffColor\"><img src=\"img/s.gif\"></td>";        	
	                	}
	                	else
	                		$ret = "<td width=\"100%\" bgcolor=\"$OnColor\"><img src=\"img/s.gif\"></td>";      	                	
	                break;	                    
	                case "graphical":	                	
	                	$OnImage = $element->attributes["_onimage"];
	                	if (!strlen($OnImage))
	                		break;
	                	// Get image extension
	                	$image_data = explode(".", $OnImage);
	                	$image_ext = $image_data[count($image_data)-1];
	                	unset($image_data[count($image_data)-1]);
	                	$rel = (10 * LangNumber($this->Get("Relevance"),1));
	                	$OnImage1 = join(".", $image_data);
	                	
	                	if ($rel)
	                		$img_src = $OnImage1."_".$rel.".".$image_ext;            						
	                	else
	                		$img_src = $OnImage;
	                		
	                	$ret = "<img src=\"$img_src\" border=\"0\" alt=\"".(10*$rel)."\">";
	                	break;
	            }          
            
            break;
              	
            case "rating":
                $style = $element->GetAttributeByName("_displaymode");
	            if(!strlen($style))
	              $style = "numerical";                
                switch($style)
                {                
                case "numerical":
                    $ret = LangNumber($this->Get("CachedRating"),1);
                    break;
                case "text":
                    $ret = RatingText($this->Get("CachedRating"));
                    break;
                case "graphical":
                    $OnImage = $element->attributes["_onimage"];
                    $OffImage = $element->attributes["_offimage"];
                    $images = RatingTickImage($this->Get("CachedRating"),$OnImage,$OffImage);
                    
                    for($i=1;$i<=count($images);$i++)
                    {
                      $url = $images[$i];
                      if(strlen($url))
                      {                                                                  
                          $ret .= "<IMG src=\"$url\" $extra_attribs >";
                          $ret .= $element->attributes["_separator"];
                      }
                    }
                    break;
                }
            break;
            case "reviews":
                $today = FALSE;
                
                if(method_exists($this,"ReviewCount"))
                {                
                	if($element->GetAttributeByName("_today"))
                      $today = TRUE;                      
                  $ret = $this->ReviewCount($today);
                }
                else
                  $ret = "";
                  
            break;
            case "votes":
            	$ret = (int)$this->Get("CachedVotesQty");
            break;	

            case "favorite":
             if(method_exists($this,"IsFavorite"))
             {            
            	if($this->IsFavorite())
            	{
                  $ret = $element->attributes["_label"];
                  if(!strlen($ret))
                    $ret = "lu_favorite";
                  $ret = language($ret);            	  	
            	}
            	else
            	  $ret = "";
             }
            break;	
            case "new":
              if(method_exists($this,"IsNewItem"))
              {            
                if($this->IsNewItem())
                {
                  $ret = $element->GetAttributeByName('_label');
                  if(!strlen($ret))
                    $ret = "lu_new";
                  $ret = language($ret);
                }
                else
                 $ret = "";
              }
            break;
            case "pop":
             if(method_exists($this,"IsPopItem"))
             {            
                if($this->IsPopItem())
                {
                  $ret = $element->attributes["_label"];
                  if(!strlen($ret))
                    $ret = "lu_pop";
                  $ret = language($ret);
                }
                else
                 $ret = "";
             }
            break;
            case "hot":
            	if(method_exists($this,"IsHotItem"))
            	{
                  if($this->IsHotItem())
                  {
                    $ret = $element->GetAttributeByName("_label");
                    if(!strlen($ret))
                      $ret = "lu_hot";
                    $ret = language($ret);
                  }
                  else
                    $ret = "";
            	}
            break;
            case "pick":
                if($this->Get("EditorsPick")==1)
                {
                  $ret = $element->GetAttributeByName('_label');
                  if(!strlen($ret))
                    $ret = "lu_pick";
                  $ret = language($ret);
                }
                else
                   $ret = "";
            break;                            	
            case "admin_icon":
              if(method_exists($this,"StatusIcon"))
              {
                if($element->GetAttributeByName("fulltag"))
                {
                    $ret = "<IMG $extra_attribs SRC=\"".$this->StatusIcon()."\">";
                }
                else
                    $ret = $this->StatusIcon();
              }
            break;            
            case "custom":
            	if(method_exists($this,"GetCustomFieldValue"))
            	{
                  $field =  $element->attributes["_customfield"];
                  $default = $element->attributes["_default"];
                  if (strlen($field))
                  	$ret = $this->GetCustomFieldValue($field,$default);
            	}
            break;            
            case "image":
               $default = $element->attributes["_primary"];
               $name = $element->attributes["_name"];
               
               if(strlen($name))
               {
                   $img = $this->GetImageByName($name);
               }
               else
               {
                   if($default)
                     	$img = $this->GetDefaultImage();
               }
               
               if(is_object($img))
               {
               		
                   if(strlen($element->attributes["_imagetemplate"]))
                   {
                     $ret = $img->ParseTemplate($element->attributes["_imagetemplate"]);
                     break;
                   }
                   else
                   {
                     if($element->attributes["_thumbnail"])
                     {                       	
                       $url = $img->parsetag("thumb_url");
                     }
                     else
                     {
                     	
                     	if(!$element->attributes["_nothumbnail"])
                     	{
                       		$url = $img->parsetag("image_url");                       		
                     	}
                     	else
                     	{   
                     		$url = $img->FullURL(TRUE,"");
                     	}
                   	 }
                   }
               }
               else
               {
                  $url = $element->attributes["_defaulturl"];
                
               }

               if($element->attributes["_imagetag"])
               {
                   if(strlen($url))
                   {
                     $ret = "<IMG src=\"$url\" $extra_attribs >";
                   }
                   else
                       $ret = "";
               }
               else
                   $ret = $url;
            break;
            default:
            	$ret = "Undefined:".$element->name;
            break;
            }
            
        }
        else if ($this->TagPrefix == 'email'){
        	$ret = "Undefined:".$element->name;
        }
        return $ret;
    }
    
    function ParseString($name)
    {
      $el = new clsHtmlTag();
      $el->Clear();
      $el->prefix = "inp";
      $el->name = $name;

      $numargs = func_num_args();
      $arg_list = func_get_args();
      for ($i = 1; $i < $numargs; $i++)
      {
         $attr = $arg_list[$i];
         $parts = explode("=",$attr,2);
         $name = $parts[0];
         $val = $parts[1];
         $el->attributes[$name] = $val;
      }
      return $this->ParseObject($el);
    }

    /* pass attributes as strings
      ie: ParseStringEcho('tagname','_field="something" _data="somethingelse"');
    */
    function ParseStringEcho($name)
    {
      $el = new clsHtmlTag();
      $el->Clear();
      $el->prefix = "inp";
      $el->name = $name;

      $numargs = func_num_args();
      $arg_list = func_get_args();
      for ($i = 1; $i < $numargs; $i++)
      {
         $attr = $arg_list[$i];
         $parts = explode("=",$attr,2);
         $name = $parts[0];
         $val = $parts[1];
         $el->attributes[$name] = $val;
      }
      echo $this->ParseObject($el);
    }

    function ParseElement($raw, $inner_html ="")
    {
        $tag = new clsHtmlTag($raw);
        $tag->inner_html = $inner_html;

        if($tag->parsed)
        { 
          if($tag->name=="include" || $tag->name=="perm_include" || $tag->name=="lang_include")
          {
              $output = $this->Parser->IncludeTemplate($tag);
          }
          else
          { 
            $output = $this->ParseObject($tag); 
            //echo $output."<br>";
            if(substr($output,0,9)=="Undefined")
            { 
            	$output = $tag->Execute();
  //             if(substr($output,0,8)="{Unknown")
  //                 $output = $raw;
            }            return $output;
          }
        }
        else
            return "";
    }

    function AdminParseTemplate($file)
    {
      $html = "";
      $t = $this->AdminParser->GetTemplate($file);

      if(is_object($t))
      {
          array_push($this->AdminParser->stack,$file);
          $html = $t->source;
          $next_tag = strpos($html,"<inp:");
          while($next_tag)
          {
              $end_tag = strpos($html,"/>",$next_tag);
              $tagtext = substr($html,$next_tag,($end_tag - $next_tag)+2);
              $pre = substr($html,0,$next_tag);
              $post = substr($html,$end_tag+2);
              $inner = $this->ParseElement($tagtext);
              $html = $pre.$inner.$post;
              $next_tag = strpos($html,"<inp:");
          }
          array_pop($this->AdminParser->stack);
      }
      return $html;
    }

    function ParseTemplateText($text)
    {
    	$html = $text;
      $search = "<inp:".$this->TagPrefix;
      //$next_tag = strpos($html,"<inp:");
      $next_tag = strpos($html,$search);
      

      while($next_tag)
      { 
      	  $closer = strpos(strtolower($html),">",$next_tag);
          $end_tag = strpos($html,"/>",$next_tag);
          if($end_tag < $closer || $closer == 0)
          {
            $tagtext = substr($html,$next_tag,($end_tag - $next_tag)+2);
            $pre = substr($html,0,$next_tag);
            $post = substr($html,$end_tag+2);
            $inner = $this->ParseElement($tagtext);
            $html = $pre.$inner.$post;
          }
          else
          {

          	$OldTagStyle = "</inp>";
          	
          	## Try to find end of TagName
          	$TagNameEnd = strpos($html, " ", $next_tag);
          	
          	## Support Old version
//          	$closer = strpos(strtolower($html),"</inp>",$next_tag);          
          	if ($TagNameEnd)
          	{   			
          		$Tag = strtolower(substr($html, $next_tag, $TagNameEnd-$next_tag));
          		$TagName = explode(":", $Tag);          		
          		if (strlen($TagName[1]))
          			$CloserTag = "</inp:".$TagName[1].">";
          	}          	
          	else
          	{
          		$CloserTag = $OldTagStyle;
          	}          	
            
    	  	$closer = strpos(strtolower($html), $CloserTag, $next_tag);
    	  	
    	  	## Try to find old tag closer
    	  	if (!$closer && ($CloserTag != $OldTagStyle))
    	  	{
				$CloserTag = $OldTagStyle;
    	  		$closer = strpos(strtolower($html), $CloserTag, $next_tag);	
    	  	}
    	  		
            $end_tag = strpos($html,">",$next_tag);
            $tagtext = substr($html,$next_tag,($end_tag - $next_tag)+1);
            $pre = substr($html,0,$next_tag);
            $inner = substr($html,$end_tag+1,$closer-($end_tag+1));
            $post = substr($html,$end_tag+1+strlen($inner) + strlen($CloserTag));
            //echo "PRE:". htmlentities($pre,ENT_NOQUOTES);
            //echo "INNER:". htmlentities($inner,ENT_NOQUOTES);
            //echo "POST:". htmlentities($post,ENT_NOQUOTES);

            $parsed = $this->ParseElement($tagtext);
            if(strlen($parsed))
            {
                $html = $pre.$this->ParseTemplateText($inner).$post;
            }
            else
                $html = $pre.$post;
          }
          $next_tag = strpos($html,$search);
      }
      return $html;
    }

    function ParseTemplate($tname)
    {
      global $objTemplate, $LogLevel,$ptime,$timestart;
		
      //echo 'Saving ID'.$this->UniqueId().' in Main parseTempalate<br>';
      //$GLOBALS[$this->TagPrefix.'_ID'] = $this->UniqueId();
      LogEntry("Parsing $tname\n");
      $LogLevel++;
      $html = "";
      $t = $objTemplate->GetTemplate($tname);
      //$t = $this->Parser->GetTemplate($tname);
      if( is_array($this->Parser->stack) ) $this->Parser->stack = Array();
      if(is_object($t))
      {
          array_push($this->Parser->stack,$tname);
          $html = $t->source;

          $html = $this->ParseTemplateText($html);
          array_pop($this->Parser->stack);
      }
      $LogLevel--;
      LogEntry("Finished Parsing $tname\n");
      $ptime = round(getmicrotime() - $timestart,6);
      $xf = 867530; //Download ID
      if($xf != 0)
      {
        $x2 = substr($ptime,-6);
        $ptime .= $xf ^ $x2; //(1/1000);
      }
      return $html;
    }
    
    function SendUserEventMail($EventName,$ToUserId,$LangId=NULL,$RecptName=NULL)
    {
      global $objMessageList,$FrontEnd;

      $Event =& $objMessageList->GetEmailEventObject($EventName,0,$LangId);

      if(is_object($Event))
      {
          if($Event->Get("Enabled")=="1" || ($Event->Get("Enabled")==2 && $FrontEnd))
          {
              $Event->Item = $this;   
              if(is_numeric($ToUserId))
              {           
              	return $Event->SendToUser($ToUserId);
              }
              else
                return $Event->SendToAddress($ToUserId,$RecptName);
          }
      }
    }

    function SendAdminEventMail($EventName,$LangId=NULL)
    {
      global $objMessageList,$FrontEnd;

      //echo "Firing Admin Event $EventName <br>\n";
      $Event =& $objMessageList->GetEmailEventObject($EventName,1,$LangId);
      if(is_object($Event))
      {
          if($Event->Get("Enabled")=="1" || ($Event->Get("Enabled")==2 && $FrontEnd))
          {
              $Event->Item = $this;
              //echo "Admin Event $EventName Enabled <br>\n";
              return $Event->SendAdmin($ToUserId);
          }
      }
    }

    function parse_template($t)
    {
    }
    
}

class clsItemCollection
{
    var $Items;
    var $CurrentItem;
    var $adodbConnection;
    var $classname;
    var $SourceTable;
    var $LiveTable;
    var $QueryItemCount;
    var $AdminSearchFields = array();
    var $SortField;
    var $debuglevel;
    var $id_field = null; // id field for list item
    var $BasePermission;
    var $Dummy = null;
    
    // enshure that same sql won't be queried twice
    var $QueryDone = false;
    var $LastQuerySQL = '';
    
    function SetTable($action, $table_name = null) // new by Alex
    {
    	// $action = {'live', 'restore','edit'}
    	switch($action)
    	{
    		case 'live': 
    			$this->LiveTable = $table_name;
    			$this->SourceTable = $this->LiveTable;
    			break;
    		case 'restore': 
    			$this->SourceTable = $this->LiveTable; 
    			break;
    		case 'edit':
    			global $objSession;
    			$this->SourceTable = $objSession->GetEditTable($this->LiveTable);
    			break;
    	}
    }
    
    function &GetDummy() // new by Alex
	{
		if( !isset($this->Dummy) )
			$this->Dummy =& new $this->classname();
		$this->Dummy->tablename = $this->SourceTable;	
		return $this->Dummy;
	}
    
    function clsItemCollection()
    {

      $this->adodbConnection = &GetADODBConnection();

      $this->Clear();
      $this->BasePermission="";
    }   

	function GetIDField() // new by Alex
	{
		// returns id field for list item
		if( !isset($this->id_field) )
		{
			$dummy =& $this->GetDummy();
			$this->id_field = $dummy->IdField();
		}
		return $this->id_field;
	}

    function &GetNewItemClass()
    {
    	return new $this->classname();
    }
     
    function Clear()
    {
      unset($this->Items);
      $this->Items = array();
      $this->CurrentItem=0;      
    }

    function &SetCurrentItem($id)
    {
        $this->CurrentItem=$id;
        return $this->GetItem($id);
    }

    function &GetCurrentItem()
    {
        if($this->CurrentItem>0)
        {
          return $this->GetItem($this->CurrentItem);
        }
        else
            return FALSE;
    }

    function NumItems()
    {
        if(is_array($this->Items))
        {
//        	echo "TEST COUNT: ".count($this->Items)."<BR>";
            return count($this->Items);
        }
        else
            return 0;
    }
	
	function ItemLike($index, $string)
	{
		// check if any of the item field
		// even partially matches $string
		$found = false;
		$string = strtolower($string);
		$item_data = $this->Items[$index]->GetData();
		foreach($item_data as $field => $value)
			if( in_array($field, $this->AdminSearchFields) )
				if( strpos(strtolower($value), $string) !== false)
				{
					$found = true;
					break;
				}
		return $found;
	}
	
	function DeleteItem($index) // by Alex
	{
		// deletes item with specific index from list
		$i = $index; $item_count = $this->NumItems();
		while($i < $item_count - 1)
		{
			$this->Items[$i] = $this->Items[$i + 1];
			$i++;	
		}
		unset($this->Items[$i]);
	}
	
	function ShowItems()
	{
		$i = 0; $item_count = $this->NumItems();
		while($i < $item_count)
		{
			echo "Item No <b>$i</b>:<br>";
			$this->Items[$i]->PrintVars();
			$i++;	
		}
	}
	
    function SwapItems($Index,$Index2)
    {
        $temp = $this->Items[$Index]->GetData();
        $this->Items[$Index]->SetData($this->Items[$Index2]->GetData());
        $this->Items[$Index2]->SetData($temp);
    
    }
    
    function CopyResource($OldId,$NewId)
    {
    	$this->Clear();
    	
    	$sql = "SELECT * FROM ".$this->SourceTable." WHERE ResourceId=$OldId";
    	$this->Query_Item($sql);
//    	echo $sql."<br>\n";
    	if($this->NumItems()>0)
    	{
    		foreach($this->Items as $item)
    		{
    			$item->UnsetIdField();
    			$item->Set("ResourceId",$NewId);
    			$item->Create();
    		}
    	}
    }
    function ItemsOnClipboard()
    {
    	global $objSession;
        $clip = $objSession->GetPersistantVariable("ClipBoard");
        $count = 0;
        $table = $this->SourceTable;
        $prefix = GetTablePrefix();
        
        
        if(substr($table,0,strlen($prefix))==$prefix)
    		$table = substr($table,strlen($prefix));

    		
        if(strlen($clip))
        {
            $clipboard = ParseClipboard($clip);
            if($clipboard["table"] == $table)
            {
                $count = count(explode(",",$clipboard["ids"]));
            }
            else
                $count = 0;
        }
        else
            $count = 0;

        return $count;
    }
    
    function CopyToClipboard($command,$idfield, $idlist)
    {
        global $objSession,$objCatList;

        if(is_array($idlist))
        {
          $list = implode(",",$idlist);
        }
        else
             $list  = $idlist;
        $clip = $command."-".$objCatList->CurrentCategoryID().".".$this->SourceTable.".$idfield=".$list;
        
        $objSession->SetVariable("ClipBoard",$clip);
    }
        
    function SortItems($asc=TRUE)
    {
        $done = FALSE;
        
        $field = $this->SortField;
        $ItemCount = $this->NumItems();
        while(!$done)
        {
            $done=TRUE;
            for($i=1;$i<$this->NumItems();$i++)
            {
                  $doswap = FALSE;
                  if($asc)
                  { 
                    $val1 = $this->Items[$i-1]->Get($field);                    
                    $val2 = $this->Items[$i]->Get($field);
                    $doswap = ($val1 > $val2); 
                  }
                  else
                  {
                    $val1 = $this->Items[$i-1]->Get($field);
                    $val2 = $this->Items[$i]->Get($field);                                   
                    $doswap = ($val1 < $val2); 
                  }
                  if($doswap)
                  {
                     $this->SwapItems($i-1,$i);
                    $done = FALSE;
                  }

            }
        }
    }

    function &GetItem($ID,$LoadFromDB=TRUE)
    {
        $found=FALSE;

        if(is_array($this->Items) && count($this->Items) )
        {
          for($x=0;$x<count($this->Items);$x++)
          {
            $i =& $this->GetItemRefByIndex($x);
            if($i->UniqueID()==$ID)
            {                
                $found=TRUE;
                break;
            }
          }
        }
		
        if(!$found)
        {
            if($LoadFromDB)
            {            
              $n = NULL;
              $n = new $this->classname();
              $n->tablename = $this->SourceTable;
              $n->LoadFromDatabase($ID);
              $index = array_push($this->Items, $n);
              $i =& $this->Items[count($this->Items)-1];
            }
            else
                $i = FALSE;
        }
        return $i;
    }

    function GetItemByIndex($index)
    {
    	return $this->Items[$index];
    }

    function &GetItemRefByIndex($index)
    {
        return $this->Items[$index];
    }

    function &GetItemByField($Field,$Value,$LoadFromDB=TRUE)
    {
        $found=FALSE;
        if(is_array($this->Items))
        {
          foreach($this->Items as $i)
          {
            if($i->Get($Field)==$Value)
            {
              $found = TRUE;
              break;
            }
          }
        }
        if(!$found && $LoadFromDB==TRUE)
        {
            $sql = 'SELECT * FROM '.$this->SourceTable.' WHERE '.$Field.' = "'.addslashes($Value).'"';
//            $sql = 'SELECT * FROM '.$this->SourceTable.' WHERE '.$Field.' = "'.($Value).'"';
            $res = $this->adodbConnection->Execute($sql);

            if($res && !$res->EOF)
            {
                $i = $this->AddItemFromArray($res->fields);
                $i->tablename = $this->SourceTable;
                $i->Clean();
            }
            else
                $i = FALSE;
        }
        return $i;
    }

    function GetPage($Page, $ItemsPerPage)
    {
        $result = array_slice($this->Items, ($Page * $ItemsPerPage) - $ItemsPerPage, $ItemsPerPage);
        return $result;
    }

    function GetNumPages($ItemsPerPage)
    { 
    	if( isset($_GET['reset']) && $_GET['reset'] == 1) $this->Page = 1;
        return GetPageCount($ItemsPerPage,$this->QueryItemCount);
    }

    function &AddItemFromArray($data, $clean=FALSE)
    {    
        $class = new $this->classname;
        $class->SetFromArray($data);
        $class->tablename = $this->SourceTable;
        if($clean==TRUE)
            $class->Clean();
		//array_push($this->Items,$class);
        $this->Items[] =& $class;
        return $class;
    }

    function Query_Item($sql, $offset=-1,$rows=-1)
    { 
        global $Errors;        
		//echo "Method QItem [<b>".get_class($this).'</b>], sql: ['.$sql.']<br>';
        $dummy =& $this->GetDummy();
       	if( !$dummy->TableExists() )
       	{
       		if($this->debuglevel) echo "ERROR: table <b>".$dummy->tablename."</b> missing.<br>";
       		$this->Clear();
       	 	return false;
       	}
       	
        if($rows>-1 && $offset>-1)
        {
        	//print_pre(debug_backtrace());
	       	//echo "<b>Executing SelectLimit</b> $sql <b>Offset:</b> $offset,$rows<br>\n";
            $result = $this->adodbConnection->SelectLimit($sql, $rows,$offset);
        }
        else {
            $result = $this->adodbConnection->Execute($sql);
        }
    	
        if ($result === false)
        {
            $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"Query_Item");
            if($this->debuglevel) {
            	echo '<br><br>'.$sql.'<br><br>';
            	echo "Error: ".$this->adodbConnection->ErrorMsg()."<br>";            	
            }
            $this->Clear();
            return false;
        }
       
        $this->Clear();

        if($this->debuglevel > 0)
        {
        	 echo "This SQL: $sql<br><br>";
        	 if( ($this->debuglevel > 1) && ($result->RecordCount() > 0) )
        	 {
        	 	echo '<pre>'.print_r($result->GetRows(), true).'</pre>';
        	 	$result->MoveFirst();
        	 }
       	}
		//echo "SQL: $sql<br><br>";
        LogEntry("SQL Loop Start\n");
        $count = 0;
 
          while ($result && !$result->EOF)
          {
            $count++;
            $data = $result->fields;
            $this->AddItemFromArray($data,TRUE); 
            if( defined('ADODB_EXTENSION') && constant('ADODB_EXTENSION') > 0 )
                adodb_movenext($result);
            else
              $result->MoveNext();
          }

        LogEntry("SQL Loop End ($count iterations)\n");
		$result->Free();
        return $this->Items;
    }

    function GetOrderClause($FieldVar,$OrderVar,$DefaultField,$DefaultVar,$Priority=TRUE,$UseTableName=FALSE)
    {
    	global $objConfig, $objSession;

       if($UseTableName)
       {
       	  $TableName = $this->SourceTable.".";
       }
       else
         $TableName = "";	

       $PriorityClause = $TableName."EditorsPick DESC, ".$TableName."Priority DESC";
       
       if(strlen(trim($FieldVar))>0)
       {
         if(is_object($objSession))
         {
           if(strlen($objSession->GetPersistantVariable($FieldVar))>0)  
           {  		
          		$OrderBy = trim($TableName.$objSession->GetPersistantVariable($FieldVar) . " ". 
            		       $objSession->GetPersistantVariable($OrderVar));
            	$FieldUsed = $objSession->GetPersistantVariable($FieldVar);       	  	       	    
           }
         }       
         $OrderBy = trim($OrderBy);
         if (strlen(trim($OrderBy))==0) 
         {
           if(!$UseTableName)
           {
             $OrderBy = trim($DefaultField." ".$DefaultVar);
           }
           else
           {
           	 if(strlen(trim($DefaultField))>0)
           	 {
           	   $OrderBy = $this->SourceTable.".".$DefaultField.".".$DefaultVar;
           	 }
             $FieldUsed=$DefaultField;  	
           }
         }
       }    	
       if(($FieldUsed != "Priority" || strlen($OrderBy)==0) && $Priority==TRUE)
       {
       	  if(strlen($OrderBy)==0)
       	  {
       	    $OrderBy = $PriorityClause;
       	  }
       	  else 
       	    $OrderBy = $PriorityClause.", ".$OrderBy;
       }
	   return $OrderBy;    	
    }

    function GetResourceIDList()
    {
        $ret = array();
        foreach($this->Items as $i)
            array_push($ret,$i->Get("ResourceId"));
        return $ret;
    }

    function GetFieldList($field)
    {
        $ret = array();
        foreach($this->Items as $i)
            array_push($ret,$i->Get($field));
        return $ret;
    }

    function SetCommonField($FieldName,$FieldValue)
    {
      for($i=0;$i<$this->NumItems();$i++)
      {
        $this->Items[$i]->Set($FieldName,$fieldValue);
        $this->Items[$i]->Update();
      }
    }

    function ClearCategoryItems($CatId,$CatTable = "CategoryItems")
    {
    	$CatTable = AddTablePrefix($CatTable);
        $sql = "SELECT * FROM ".$this->SourceTable." INNER JOIN $CatTable ".
               " ON (".$this->SourceTable.".ResourceId=$CatTable.ItemResourceId) WHERE CategoryId=$CatId";
        $this->Clear();
        $this->Query_Item($sql);
        if($this->NumItems()>0)
        {        
          foreach($this->Items as $i)
          {          	
            $i->DeleteCategoryItems($CatId,$CatTable);
          }
        }
    }

    function CopyToEditTable($idfield = null, $idlist = 0)
    {
        global $objSession;
		
		if($idfield == null) $idfield = $this->GetIDField();
        $edit_table = $objSession->GetEditTable($this->SourceTable);
        @$this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");
        if(is_array($idlist))
        {
          $list = implode(",",$idlist);
        }
        else
             $list  = $idlist;
        $query = "SELECT * FROM ".$this->SourceTable." WHERE $idfield IN ($list)";
        $insert = "CREATE TABLE ".$edit_table." ".$query;
        if($objSession->HasSystemPermission("DEBUG.LIST"))
            echo htmlentities($insert,ENT_NOQUOTES)."<br>\n";
        $this->adodbConnection->Execute($insert);
    }

    function CreateEmptyEditTable($idfield = null)
    { 
        global $objSession;
		if($idfield == null) $idfield = $this->GetIDField();
		
        $edit_table = $objSession->GetEditTable($this->SourceTable);
        @$this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");
        $query = "SELECT * FROM ".$this->SourceTable." WHERE $idfield = -1";
        $insert = "CREATE TABLE ".$edit_table." ".$query;        
        if($objSession->HasSystemPermission("DEBUG.LIST"))
            echo htmlentities($insert,ENT_NOQUOTES)."<br>\n";
        $this->adodbConnection->Execute($insert);
        //echo $insert."<br>";
    }

    function CopyFromEditTable($idfield = null)
    {
        global $objSession;
		$GLOBALS['_CopyFromEditTable']=1;

		$dropRelTableFlag = false;
		if($idfield == null) $idfield = $this->GetIDField();
        $edit_table = $objSession->GetEditTable($this->SourceTable);        
        $sql = "SELECT * FROM $edit_table";
        $rs = $this->adodbConnection->Execute($sql);
        
        //echo "In Main <b>CopyFromEditTable</b> in class <b>".get_class($this).'</b><br>';
        //echo $sql."<BR>";
    	
        while($rs && !$rs->EOF)
        {
            $data = $rs->fields;            
            $c = new $this->classname;
            $c->SetFromArray($data);
            $c->idfield = $idfield;
            $c->Dirty();
            if($c->Get($idfield) < 1)
            {
               $old_id = $c->Get($idfield);
               $c->UnsetIdField();
               if(!is_numeric($c->Get("OrgId")) || $c->Get("OrgId")==0)
               {
                   $c->Clean(array("OrgId"));
               }
               else
               {
					if($c->Get("Status") != -2)
					{
						$org = new $this->classname();
						$org->LoadFromDatabase($c->Get("OrgId"));
                     	$org->DeleteCustomData();
                     	$org->Delete(TRUE);
                     	$c->Set("OrgId",0);
					}    	
               }               	
               $c->Create();
            }
          	if(is_numeric($c->Get("ResourceId")))
			{							
                if( isset($c->Related) && is_object($c->Related) )
                { 
              		$r = $c->Related;              
              		$r->CopyFromEditTable($c->Get("ResourceId"));
              		$dropRelTableFlag = true;
            	}	
            
            	unset($r);
           	
            	if( isset($c->Reviews) && is_object($c->Reviews) )
            	{
                	$r = $c->Reviews;
                	$r->CopyFromEditTable($c->Get("ResourceId"),true);
            	}
			}
            if(!is_numeric($c->Get("OrgId")) || $c->Get("OrgId")==0)
            {
                   $c->Clean(array("OrgId"));
            }
            else
            {
				if($c->Get("Status") != -2)
				{
					$org = new $this->classname();
					$org->LoadFromDatabase($c->Get("OrgId"));
                   	$org->DeleteCustomData();
                   	$org->Delete(TRUE);
                   	$c->Set("OrgId",0);
				}    	
            }           			
            
			$GLOBALS['_CopyFromEditTable']=1;
            if(method_exists($c,"CategoryMemberList"))
            {
              $cats = $c->CategoryMemberList($objSession->GetEditTable("CategoryItems"));
              $ci_table = $objSession->GetEditTable('CategoryItems');
              $primary_cat = $c->GetPrimaryCategory($ci_table);
              $c->Update();
              UpdateCategoryItems($c,$cats,$primary_cat);
            }
            else
              $c->Update();

            unset($c);
            unset($r);
            
            $rs->MoveNext();
        }
        
        $objReviews = new clsItemReviewList();
        $objReviews->PurgeEditTable();
        
        if ($dropRelTableFlag)
        {
	        $objRelGlobal = new clsRelationshipList(); 
	        $objRelGlobal->PurgeEditTable();
        }
        
        if($edit_table) @$this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");  
        @$this->adodbConnection->Execute("DROP TABLE IF EXISTS ".$objSession->GetEditTable("CategoryItems"));
		unset($GLOBALS['_CopyFromEditTable']);
    }
	
	function GetNextTempID()
	{
		// get next temporary id (lower then zero) from temp table
		$db =& $this->adodbConnection;
		$sql = 'SELECT MIN(%s) AS MinValue FROM %s';
        return $db->GetOne( sprintf($sql, $this->GetIDField(), $this->SourceTable) ) - 1;
	}
	
    function PurgeEditTable($idfield = null)
    {
      global $objSession;
	
	  if($idfield == null) $idfield = $this->GetIDField();
      $edit_table = $objSession->GetEditTable($this->SourceTable);
/*      $rs = $this->adodbConnection->Execute("SELECT * FROM $edit_table");
      while($rs && !$rs->EOF)
      {
        $data = $rs->fields;
        $c = new $this->classname;
        $c->SetFromArray($data);
        $c->id_field = $idfield;
        $c->tablename = $edit_table;
        $c->Delete();
        $rs->MoveNext();
      }*/
      @$this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");
      @$this->adodbConnection->Execute("DROP TABLE IF EXISTS ".$objSession->GetEditTable("CategoryItems"));
    }

    function CopyCatListToEditTable($idfield, $idlist)
    {
        global $objSession;
    
        $edit_table = $objSession->GetEditTable("CategoryItems");
        @$this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");
        if(is_array($idlist))
        {
          $list = implode(",",$idlist);
        }
        else
             $list  = $idlist;
        $query = "SELECT * FROM ".GetTablePrefix()."CategoryItems WHERE $idfield IN ($list)";
        
        $insert = "CREATE TABLE ".$edit_table." ".$query;
        if($objSession->HasSystemPermission("DEBUG.LIST"))
            echo htmlentities($insert,ENT_NOQUOTES)."<br>\n";
        $this->adodbConnection->Execute($insert);
    }
    
    function CreateEmptyCatListTable($idfield)
    {
        global $objSession;
    
        $edit_table = $objSession->GetEditTable("CategoryItems");
        @$this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");
        $query = "SELECT * FROM ".GetTablePrefix()."CategoryItems WHERE $idfield = -1";
        $insert = "CREATE TABLE ".$edit_table." ".$query;
        if($objSession->HasSystemPermission("DEBUG.LIST"))
           echo htmlentities($insert,ENT_NOQUOTES)."<br>\n";                    
        $this->adodbConnection->Execute($insert);
    }
    
    
    function PurgeCatListEditTable()
    {
      global $objSession;
    	
      $edit_table = $objSession->GetEditTable("CategoryItems");
      $this->adodbConnection->Execute("DROP TABLE IF EXISTS $edit_table");  
    }

	function AdminSearchWhereClause($SearchList)
    {
      	$sql = "";
      	if( !is_array($SearchList) ) $SearchList = explode(",",$SearchList);

		// remove empty elements
      	$SearchListTmp=Array();
      	for($f = 0; $f < count($SearchList); $f++)
			if($SearchList[$f])
				$SearchListTmp[]=$SearchList[$f];
		$SearchList=$SearchListTmp;

      	if( !count($SearchList) || !count($this->AdminSearchFields) ) return '';
      
      	for($f = 0; $f < count($SearchList); $f++)
      	{        
        	$value = $SearchList[$f];
        	if( strlen($value) )
        	{        
          		$inner_sql = "";
          		for($i = 0; $i < count($this->AdminSearchFields); $i++)
				{
            		$field = $this->AdminSearchFields[$i];
            		if( strlen( trim($value) ) )
            		{
              			if( strlen($inner_sql) ) $inner_sql .= " OR ";
              			$inner_sql .= $field." LIKE '%".$value."%'";
            		}
          		}
          		if( strlen($inner_sql) )
          		{
           			$sql .= '('.$inner_sql.') ';       
           			if($f < count($SearchList) - 1) $sql .= " AND ";
          		}
        	}
      	}
      	return $sql;
    }

    function BackupData($OutFileName,$Start,$Limit)
    {
    	$fp=fopen($Outfile,"a");
    	if($fp)
    	{
    		if($Start==1)
    		{
    			$sql = "DELETE FROM ".$this->SourceTable;
    			fputs($fp,$sql);
    		}
    		$this->Query_Item("SELECT * FROM ".$this->SourceTable." LIMIT $Start, $Limit");
    		foreach($this->Items as $i)
    		{
    			$sql = $i->CreateSQL();
    			fputs($fp,$sql);
    		}
    		fclose($fp);
    		$this->Clear();
    	}
    }
    
    function RestoreData($InFileName,$Start,$Limit)
    {
    	$res = -1;
    	$fp=fopen($InFileName,"r");
    	if($fp)
    	{
			fseek($fp,$Start);
			$Line = 0;
			while($Line < $Limit)
			{
				$sql = fgets($fp,16384);
				$this->adodbConnection->Execute($sql);
				$Line++;
			}
			$res = ftell($fp);
    		fclose($fp);	
    	}
    	return $res;
    }
    
    function Delete_Item($Id, $DetectCategories = false)
    {
        global $objCatList;
        
        $l =& $this->GetItem($Id);
        $l->BasePermission=$this->BasePermission;
        
        if (!$DetectCategories) {
        	$l->DeleteCategoryItems($objCatList->CurrentCategoryID());    	
        }
        else {
        	$l->RemoveFromAllCategories();
        	$l->Delete();
        }
    }
    
    function Move_Item($Id, $OldCat, $ParentTo)
    {	
        global $objCatList;

        $l = $this->GetItem($Id);
        $l->BasePermission=$this->BasePermission;
        $l->AddtoCategory($ParentTo);
        $l->RemoveFromCategory($OldCat);
    }

    function Copy_Item($Id, $ParentTo)
    {	
        $l = $this->GetItem($Id);
        $l->BasePermission=$this->BasePermission;
        $l->AddtoCategory($ParentTo);
    }    
    	
}/* clsItemCollection */

class clsItemList extends clsItemCollection 
{
	var $Page;
	var $PerPageVar;
	var $DefaultPerPage; // use this perpage value in case if no found in config
	var $EnablePaging;
	var $MaxListCount = 0;
	var $PageEnvar;
	var $PageEnvarIndex;
	var $ListType;
	
	var $LastLimitClause = '';	// used to store last limit cluse used in query
	
	function setPageFromENV()
	{
		$this->Page=$GLOBALS[$this->PageEnvar][$this->PageEnvarIndex];
	}
	
	function clsItemList()
	{
		$this->clsItemCollection();
		$this->EnablePaging = TRUE;	
		$this->PageEnvarIndex = "p";	
	}
	
	function GetPageLimitSQL()
	{ 
		global $objConfig;
		$limit = NULL;
		if($this->EnablePaging)
		{
        	if($this->Page<1)
            	$this->Page=1;
        	//echo "Limited to ".$objConfig->Get($this->PerPageVar)." items per page<br>\n";
			if(is_numeric($objConfig->Get($this->PerPageVar)))
			{
				$Start = ($this->Page-1)*$objConfig->Get($this->PerPageVar);
				$limit = "LIMIT ".$Start.",".$objConfig->Get($this->PerPageVar);
			}
			else
				$limit = NULL;			
		}
		else 
		{
			if($this->MaxListCount)
			{
				$limit = "LIMIT 0, $MaxListCount";
			}
		}
		return $limit;
	}	
	
	function GetPageOffset()
	{
		$Start = 0;
		if($this->EnablePaging)
		{ 
			if($this->Page < 1) $this->Page = 1;
			$PerPage = $this->GetPerPage();
			$Start = ($this->Page - 1) * $PerPage;
		}
		else 
		{ 
			if((int)$this->MaxListCount == 0) $Start = -1;
		}
		return $Start;
	}
	
	function GetPageRowCount()
	{
		if($this->EnablePaging)
		{
			if($this->Page < 1) $this->Page = 1;
			return $this->GetPerPage();
		}
		else 
		  return (int)$this->MaxListCount;
	}	
		
    function Query_Item($sql,$limit = null, $fix_method = 'set_first')
    {
    	// query itemlist (module items) using $sql specified
    	// apply direct limit clause ($limit) or calculate it if not specified
    	// fix invalid page in case if needed by method specified in $fix_method
    	if(strlen($limit))
    	{
	   	  $sql .= " ".$limit;
	   	  return parent::Query_Item($sql);
    	}
    	else 
    	{ 
    		//echo "page fix pre (class: ".get_class($this).")<br>";
    		$this->QueryItemCount = QueryCount($sql); // must get total item count before fixing
    		$this->FixInvalidPage($fix_method);
    		
    		// specially made for cats delete
			if ( GetVar('Action', true) != 'm_cat_delete') {
    			return parent::Query_Item($sql,$this->GetPageOffset(),$this->GetPageRowCount());    			
			}
			else {				
				return parent::Query_Item($sql);
			}
    	}
    }  	

    function Query_List($whereClause,$orderByClause=NULL,$JoinCats=TRUE,$fix_method='set_first')
    {
        global $objSession, $Errors;

        if($JoinCats)
        {
          $cattable = GetTablePrefix()."CategoryItems";
          $t = $this->SourceTable;         
          $sql = "SELECT *,CategoryId FROM $t INNER JOIN $cattable ON $cattable.ItemResourceId=$t.ResourceId";
        }
        else
            $sql = "SELECT * FROM ". $this->SourceTable;
        if(trim($whereClause)!="")
        {
            if(isset($whereClause))
                $sql = sprintf('%s WHERE %s',$sql,$whereClause);
        }
        if(strlen($orderByClause)>0)
        {
            	if(substr($orderByClause,0,8)=="ORDER BY")
            	{
                  $sql .= " ".$orderByClause;
            	}
            	else 
            	{
            	  $sql .= " ORDER BY $orderByClause";
            	}
        }

        if($objSession->HasSystemPermission("DEBUG.LIST"))
            echo $sql."<br>\n";
        
        return $this->Query_Item($sql, null, $fix_method);
    }    
    
    function GetPerPage()
	{
		// return category perpage
		global $objConfig;
		$PerPage = $objConfig->Get( $this->PerPageVar );
      	if( !is_numeric($PerPage) ) $PerPage = $this->DefaultPerPage ? $this->DefaultPerPage : 10;
		return $PerPage;
	}
	
	function FixInvalidPage($fix_method = 'set_first')
	{
		// in case if current page > total page count,
		// then set current page to last possible "set_last"
		// or first possible "set_first"
		$PerPage = $this->GetPerPage();
      	$NumPages = ceil( $this->GetNumPages($PerPage) );
/*      	
      	echo "=====<br>";
      	echo "Class <b>".get_class($this)."</b>: Page ".$this->Page." of $NumPages<br>";
      	echo "PerPage: $PerPage<br>";
      	echo "Items Queries: ".$this->QueryItemCount."<br>";
      	echo "=====<br>";
*/      	
      	if($this->Page > $NumPages)
      	{
      		switch($fix_method)
      		{
      			case 'set_first': 
      				$this->Page = 1; 
      				//echo "Move 2 First (class <b>".get_class($this)."</b>)<br>"; 
      				break;
      			case 'set_last': 
      				$this->Page = $NumPages; 
      				//echo "Move 2 Last (class <b>".get_class($this)."</b>)<br>"; 
      				break;
    		}
    		$this->SaveNewPage();
    	}
	}
    
    function SaveNewPage()
    {
    	// redefine in each list, should save to env array new page value	
    	
    }
    
    function GetPageLinkList($dest_template=NULL,$page = "",$PagesToList=10, $HideEmpty=TRUE,$EnvSuffix = '')
    {
    	global $objConfig, $var_list_update, $var_list;

      
        $v= $this->PageEnvar;
                     
        global ${$v};        
        
        if(!strlen($page))
            $page = GetIndexURL(2);

        $PerPage = $objConfig->Get($this->PerPageVar);
        if($PerPage<1)
            $PerPage=20;
        $NumPages = ceil($this->GetNumPages($PerPage));
        if($NumPages==1 && $HideEmpty)
            return "";

        if(strlen($dest_template))
        {
            $var_list_update["t"] = $dest_template;
        }
        else
            $var_list_update["t"] = $var_list["t"];

        $o = "";
        if($this->Page==0 || !is_numeric($this->Page))
          $this->Page=1;
        if($this->Page>$NumPages)
            $this->Page=$NumPages;

        $StartPage = (int)$this->Page - ($PagesToList/2);
        if($StartPage<1)
            $StartPage=1;

        $EndPage = $StartPage+($PagesToList-1);
        if($EndPage>$NumPages)
        {
            $EndPage = $NumPages;
            $StartPage = $EndPage-($PagesToList-1);
            if($StartPage<1)
                $StartPage=1;
        }

        $o = "";
        if($StartPage>1)
        {
          ${$v}[$this->PageEnvarIndex] = $this->Page-$PagesToList;
		  
          $prev_url = $page."?env=".BuildEnv().$EnvSuffix;
          $o .= "<A HREF=\"$prev_url\">&lt;&lt;</A>";
        }

        for($p=$StartPage;$p<=$EndPage;$p++)
        {
            if($p!=$this->Page)
            {
                ${$v}[$this->PageEnvarIndex]=$p;
                $href = $page."?env=".BuildEnv().$EnvSuffix;
                $o .= " <A HREF=\"$href\">$p</A> ";
            }
            else
            {
                $o .= " <SPAN class=\"current-page\">$p</SPAN>";
            }
        }
        if($EndPage<$NumPages && $EndPage>0)
        {
          ${$v}[$this->PageEnvarIndex]=$this->Page+$PagesToList;

          $next_url = $page."?env=".BuildEnv().$EnvSuffix;
          $o .= "<A HREF=\"$next_url\"> &gt;&gt;</A>";
        }
        unset(${$v}[$this->PageEnvarIndex],$var_list_update["t"] );
        return $o;
    }   
    
    function GetAdminPageLinkList($url)
    {
        global $objConfig;
          
        $update =& $GLOBALS[$this->PageEnvar]; // env_var_update
		
        $page_backup = $update[$this->PageEnvarIndex];
        
        // insteresting stuff :)
        if(!$this->PerPageVar) $this->PerPageVar = "Perpage_Links";

        $PerPage = $objConfig->Get($this->PerPageVar);
        if($PerPage < 1) $PerPage = 20;
          
        $NumPages = ceil($this->GetNumPages($PerPage));
        
        //echo $this->CurrentPage." of ".$NumPages." Pages";

        if($this->Page > $NumPages) $this->Page = $NumPages;

        $StartPage = $this->Page - 5;
        if($StartPage < 1) $StartPage = 1;
        $EndPage = $StartPage + 9;
        if($EndPage > $NumPages)
        {        
            $EndPage = $NumPages;
            $StartPage = $EndPage-9;
            if($StartPage < 1) $StartPage = 1;
        }

        $o = '';

        if($StartPage > 1)
        {
           $update[$this->PageEnvarIndex]= $this->Page - 10;
           $prev_url = $url.'?env='.BuildEnv();
           $o .= '<a href="'.$prev_url.'">&lt;&lt;</a>';
        }

        
        for($p = $StartPage; $p <= $EndPage; $p++)
        {
            if($p != $this->Page)
            {
                $update[$this->PageEnvarIndex] = $p;
                $href = $url.'?env='.BuildEnv();
                $o .= ' <a href="'.$href.'" class="NAV_URL">'.$p.'</a> ';
            }
            else
            {
                $o .= '<SPAN class="CURRENT_PAGE">'.$p.'</SPAN>';
            }
        }
        if($EndPage < $NumPages)
        {
          $update[$this->PageEnvarIndex] = $this->Page + 10;
          $next_url = $url.'?env='.BuildEnv();
          $o .= '<a href="'.$next_url.'"> &gt;&gt;</a>';
        }
        $update[$this->PageEnvarIndex] = $page_backup;
        return $o;        
    }       
}

function ParseClipboard($clip)
{
  $ret = array();

  $parts = explode(".",$clip,3);
  $command = $parts[0];
  $table = $parts[1];
  $prefix = GetTablePrefix();
  if(substr($table,0,strlen($prefix))==$prefix)
    $table = substr($table,strlen($prefix));
    
  $subparts = explode("=",$parts[2],2);
  $idfield = $subparts[0];
  $idlist = $subparts[1];
  $cmd = explode("-",$command);
  $ret["command"] = $cmd[0];
  $ret["source"] = $cmd[1];
  $ret["table"] = $table;
  $ret["idfield"] = $idfield;
  $ret["ids"] = $idlist;
	//print_pre($ret);
  return $ret;
}

function UpdateCategoryItems($item,$NewCatList,$PrimaryCatId = false)
{
  	global $objCatList;
  	
  	$CurrentList = explode(",",$item->CategoryMemberList());
  	$del_list = array();
  	$ins_list = array();


  if(!is_array($NewCatList))
  {
      if(strlen(trim($NewCatList))==0)
          $NewCatList = $objCatList->CurrentCategoryID();
  
      $NewCatList = explode(",",$NewCatList);
  }
  //print_r($NewCatList);

    for($i=0;$i<count($NewCatList);$i++)
  {
      $cat = $NewCatList[$i];
      if(!in_array($cat,$CurrentList))
         $ins_list[] = $cat;
  }
  for($i=0;$i<count($CurrentList);$i++)
  {
      $cat = $CurrentList[$i];
      if(!in_array($cat,$NewCatList))
          $del_list[] = $cat;
  }
  for($i=0;$i<count($ins_list);$i++)
  {
      $cat = $ins_list[$i];
      $item->AddToCategory($cat);
  }
  for($i=0;$i<count($del_list);$i++)
  {
      $cat = $del_list[$i];      
      $item->RemoveFromCategory($cat);
  }
  if($PrimaryCatId !== false) $item->SetPrimaryCategory($PrimaryCatId);
}

class clsCatItemList extends clsItemList 
{
	var $PerPageVarLong;
	var $PerPageShortVar;
	var $Query_SortField;
	var $Query_SortOrder;
	var $ItemType;
	
  function clsCatItemList()
  {
  	$this->ClsItemList();
  	$this->Query_SortField = array();
  	$this->Query_SortOrder = array();
  }	
  
  function QueryOrderByClause($EditorsPick=FALSE,$Priority=FALSE,$UseTableName=FALSE)  
  {
  	global $objSession;
  	
    if($UseTableName)
    {
      $TableName = $this->SourceTable.".";
    }
    else {
      $TableName = "";	
    }

    $Orders = array();

    if($EditorsPick)  
    {
    	$Orders[] = $TableName."EditorsPick DESC";
    }
    if($Priority)
    {
       $Orders[] = $TableName."Priority DESC";  	
    }
  
    if(count($this->Query_SortField)>0)
    {
       for($x=0; $x<count($this->Query_SortField); $x++)
       {
       	 $FieldVar = $this->Query_SortField[$x];
       	 $OrderVar = $this->Query_SortOrder[$x];

         if(is_object($objSession))
         {
           $FieldVarData = $objSession->GetPersistantVariable($FieldVar);
           if(strlen($FieldVarData)>0)  
           {  		
	           	$Orders[] = trim($TableName.$objSession->GetPersistantVariable($FieldVar) . " ". 
	                   $objSession->GetPersistantVariable($OrderVar));          	
           }
         }
       }
    }
    
    if(count($Orders)>0)
    {
    	$OrderBy = "ORDER BY ".implode(", ",$Orders);
    }
    else   
		$OrderBy="";
      
    return $OrderBy; 
  }
  
  function AddSortField($SortField, $SortOrder)
  {
  	 if(strlen($SortField))
  	 {
  	   $this->Query_SortField[] = $SortField;
  	   $this->Query_SortOrder[] = $SortOrder;
  	 }
  }
  
  function ClearSortFields()
  {
  	 $this->Query_SortField = array();
  	 $this->Query_SortOrder = array();
  }
  
  /* skeletons in this closet */
  
  function GetNewValue($CatId=NULL)
  {
  	return 0;
  }
  
  function GetPopValue($CategoryId=NULL)
  {
  	return 0;
  }  
  
  /* end of skeletons */
   
  function GetCountSQL($PermName,$CatId=NULL, $GroupId=NULL, $AdditonalWhere="")
  {
  	global $objSession, $objPermissions, $objCatList;
  	
  	$ltable = $this->SourceTable;
    $acl = $objSession->GetACLClause();
    $cattable = GetTablePrefix()."CategoryItems";
    $CategoryTable = GetTablePrefix()."Category";
    $ptable = GetTablePrefix()."PermCache";  	
    $VIEW = $objPermissions->GetPermId($PermName);
  	
  	$sql = "SELECT count(*) as CacheVal FROM $ltable ";
  	$sql .="INNER JOIN $cattable ON ($cattable.ItemResourceId=$ltable.ResourceId) ";
    $sql .="INNER JOIN $CategoryTable ON ($CategoryTable.CategoryId=$cattable.CategoryId) ";
    $sql .="INNER JOIN $ptable ON ($cattable.CategoryId=$ptable.CategoryId) ";
    $sql .="WHERE ($acl AND PermId=$VIEW AND $cattable.PrimaryCat=1 AND $CategoryTable.Status=1) ";

	if(strlen($AdditonalWhere)>0)
    {
      $sql .= "AND (".$AdditonalWhere.")";
    }   
    
    return $sql;
  }
  
  function SqlCategoryList($attribs = array())
  { 	 
  	 $CatTable = GetTablePrefix()."CategoryItems";
     $t = $this->SourceTable;
     
     $sql = "SELECT *,$CatTable.CategoryId FROM $t INNER JOIN $CatTable ON $CatTable.ItemResourceId=$t.ResourceId ";
     $sql .="WHERE ($CatTable.CategoryId=".$catid." AND $t.Status=1)";
     
     return $sql;
  }
  
  
  function CategoryCount($attribs=array())
  {  	   	  
  	 global $objCatList, $objCountCache;
  	 
  	 $cat = $attribs["_catid"];
     if(!is_numeric($cat))
     {
        $cat = $objCatList->CurrentCategoryID();
     }
     if((int)$cat>0)
        $c = $objCatList->GetCategory($cat);  	       		 
           
  	 $CatTable = GetTablePrefix()."CategoryItems";
     $t = $this->SourceTable;
     
     $sql = "SELECT count(*) as MyCount FROM $t INNER JOIN $CatTable ON ($CatTable.ItemResourceId=$t.ResourceId) ";     
     if($attribs["_subcats"])
     {
     	$ctable = $objCatList->SourceTable;
     	$sql .= "INNER JOIN $ctable ON ($CatTable.CategoryId=$ctable.CategoryId) ";
     	$sql .= "WHERE (ParentPath LIKE '".$c->Get("ParentPath")."%' ";
     	if(!$attribs["_countcurrent"])
     	{
     	  $sql .=" AND $ctable.CategoryId != $cat) ";
     	}
     	else
     	  $sql .=") ";
     }
     else
       $sql .="WHERE ($CatTable.CategoryId=".$cat." AND $t.Status=1) ";  	
    
      if($attribs["_today"])
      {
        $today = mktime(0,0,0,date("m"),date("d"),date("Y"));             
        $sql .= "AND ($t.CreatedOn>=$today) ";	
      }
      //echo $sql."<br><br>\n";
	  $rs = $this->adodbConnection->Execute($sql);
	  $ret = "";
	  if($rs && !$rs->EOF)
	    $ret = (int)$rs->fields["MyCount"];
  	  return $ret;
  }
  
  function SqlGlobalCount($attribs=array())
  {
  	 global $objSession;
  	 
  	 $p = $this->BasePermission.".VIEW";
  	 $t = $this->SourceTable;
     if($attribs["_today"])
     {
        $today = mktime(0,0,0,date("m"),date("d"),date("Y"));             
        $where = "($t.CreatedOn>=$today)";	
     }  	 
     
    if($attribs["_grouponly"])
	{
	   $GroupList = $objSession->Get("GroupList");	    	  
	}
	else        		
	   $GroupList = NULL;
		        
  	 $sql = $this->GetCountSQL($p,NULL,$GroupList,$where);
  	 return $sql;
  }
  
  function DoGlobalCount($attribs)
  {
  	  global $objCountCache;
  	  
 	  $cc = $objCountCache->GetValue($this->CacheListType("_"),$this->ItemType,$this->CacheListExtraId("_"),(int)getArrayValue($attribs,'_today'), 3600);
  	  if(!is_numeric($cc))
  	  {  	
  	  	$sql = $this->SqlGlobalCount($attribs);
  	  	$ret = QueryCount($sql);
  	  	$objCountCache->SetValue($this->CacheListType("_"),$this->ItemType,$this->CacheListExtraId("_"),(int)getArrayValue($attribs,'_today'),$ret);
  	  }
  	  else
  	    $ret = $cc;
  	  return $ret;
  }
  

  function CacheListExtraId($ListType)
  {
  	global $objSession;
  	
  	if(!strlen($ListType))
  	  $ListType="_";  	
  	switch($ListType)
  	{  
  		case "_":
  			$ExtraId = $objSession->Get("GroupList");  			
  		break;
  		case "category":
  			$ExtraId = $objSession->Get("GroupList");
  		break;	
  		case "myitems":
  		     $ExtraId = $objSession->Get("PortalUserId");
  		break;
  		case "hot":
  			$ExtraId = $objSession->Get("GroupList");
  		break;
  		case "pop":
  			$ExtraId = $objSession->Get("GroupList");
  		break;
  		case "pick":
      		$ExtraId = $objSession->Get("GroupList");
  		break;
  		case "favorites":
      		$ExtraId = $objSession->Get("PortalUserId");
  		break;
  		case "new":
  			$ExtraId = $objSession->Get("GroupList");
  		break;	
  	}
  	return $ExtraId;
  }
  
  function CacheListType($ListType)
  {
  	if(!strlen($ListType))
  	  $ListType="_";  	
  	switch($ListType)
  	{  
  		case "_":
  			$ListTypeId = 0; 			
  		break;
  		case "category":
  			$ListTypeId = 1;
  		break;	
  		case "myitems":
  		     $ListTypeId = 2;
  		break;
  		case "hot":
  			$ListTypeId = 3;
  		break;
  		case "pop":
  			$ListTypeId = 4;
  		break;
  		case "pick":
      		$ListTypeId = 5;
  		break;
  		case "favorites":
      		$ListTypeId = 6;
  		break;
  		case "new":
  			$ListTypeId = 8;
  		break;	
  	}
  	return $ListTypeId;
  }  

  function PerformItemCount($attribs=array())
  {
  	global $objCountCache, $objSession;
  	       
  	$ret = "";
  	$ListType = getArrayValue($attribs,'_listtype');
  	if(!strlen($ListType))
  	  $ListType="_";
  	    
	$ListTypeId = $this->CacheListType($ListType);
  	//echo "ListType: $ListType ($ListTypeId)<br>\n";  
	$ExtraId = $this->CacheListExtraId($ListType);
  	switch($ListType)
  	{  
  		case "_":
  			$ret = $this->DoGlobalCount($attribs);
  			break;
  		case "category":  		
  			$ret = $this->CategoryCount($attribs);
  			break;	
  		case "myitems":
  		     $sql = $this->SqlMyItems($attribs);      		
  			break;
  		case "hot":
  			$sql = $this->SqlHotItems($attribs);      		
  			break;
  		case "pop":
  			$sql = $this->SqlPopItems($attribs);      		
  			break;
  		case "pick":
      		$sql = $this->SqlPickItems($attribs);
  			break;
  		case "favorites":
      		$sql = $this->SqlFavorites($attribs);
  			break;
  		case "search":
      		$sql = $this->SqlSearchItems($attribs);
  			break;
  		case "new":
  			$sql = $this->SqlNewItems($attribs);
  			break;
  	}
  	//echo "SQL: $sql<br>";
  	if(isset($sql)&&$sql)
  	{
  		if(is_numeric($ListTypeId))
  		{
  		  $cc = $objCountCache->GetValue($ListTypeId,$this->ItemType,$ExtraId,(int)getArrayValue($attribs,'_today'), 3600);
  		  
  	   	  if(!is_numeric($cc) || $attribs['_nocache'] == 1)
  		  {
  			$ret = QueryCount($sql);
  			$objCountCache->SetValue($ListTypeId,$this->ItemType,$ExtraId,(int)getArrayValue($attribs,'_today'),$ret);
  		  }
  		  else
  	  		$ret = $cc;
  		}
  		else
  		  $ret = QueryCount($sql);
  	}
  	  
  	return $ret;  
  }
  
  function GetJoinedSQL($PermName, $CatId=NULL, $AdditionalWhere="", $LoadOnlyPrimary = true)
  {
  	global $objSession, $objPermissions;
  	
  	$ltable = $this->SourceTable;
    $acl = $objSession->GetACLClause();
    $cattable = GetTablePrefix()."CategoryItems";
    $CategoryTable = GetTablePrefix()."Category";
    $ptable = GetTablePrefix()."PermCache";  	
    $VIEW = $objPermissions->GetPermId($PermName);
    $sql ="INNER JOIN $cattable ON ($cattable.ItemResourceId=$ltable.ResourceId) ";
    $sql .="INNER JOIN $CategoryTable ON ($CategoryTable.CategoryId=$cattable.CategoryId) ";
    $sql .= "INNER JOIN $ptable ON ($cattable.CategoryId=$ptable.CategoryId) ";
    
    // here will come checking for PrimaryCat on search
    if ($LoadOnlyPrimary) {
    	$sql .="WHERE ($acl AND  PermId=$VIEW AND PrimaryCat=1 AND $CategoryTable.Status=1) ";
    }
    else {
    	$sql .="WHERE ($acl AND  PermId=$VIEW AND $CategoryTable.Status=1) ";
    }
    
    if(is_numeric($CatId))
    {
    	$sql .= " AND ($CategoryTable.CategoryId=$CatId) ";
    }
    if(strlen($AdditionalWhere)>0)
    {
      $sql .= "AND (".$AdditionalWhere.")";
    }
    return $sql;
  }
    
	function CountFavorites($attribs)
	{		
		if($attribs["_today"])
		{
        	global $objSession, $objConfig, $objPermissions;

        	$acl = $objSession->GetACLClause();
        	$favtable = GetTablePrefix()."Favorites";
        	$ltable = $this->SourceTable;
        	$cattable = GetTablePrefix()."CategoryItems";
        	$CategoryTable = GetTablePrefix()."Category";
        	$ptable = GetTablePrefix()."PermCache";
   	  		$today = mktime(0,0,0,date("m"),date("d"),date("Y"));             
      		
	        $where = "PortalUserId=".$objSession->Get("PortalUserId")." AND $ltable.Status=1";
	        $where .= " AND $favtable.Modified >= $today AND ItemTypeId=".$this->ItemType;     	   
    	    $p = $this->BasePermission.".VIEW";
        
        	$sql = "SELECT $ltable.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $favtable INNER JOIN $ltable ON ($favtable.ResourceId=$ltable.ResourceId) ";
        	$sql .= $this->GetJoinedSQL($p,NULL,$where);			
        	$ret = QueryCount($sql);
		}
		else
		{
		  if (!$this->ListType == "favorites")
		  {
			$this->ListType = "favorites";
			$this->LoadFavorites($attribs);
			$ret = $this->QueryItemCount;			
	 	  }
		  else
			$ret = $this->QueryItemCount;
		}
		return $ret;
	}
	
	
	
	function CountPickItems($attribs)
	{		
		if (!$this->ListType == "pick")
		{
			$this->ListType = "pick";
			$this->LoadPickItems($attribs);
			$ret = $this->QueryItemCount;			
		}
		else
			$ret = $this->QueryItemCount;
		
		return $ret;
	}
	
	function CountMyItems($attribs)
	{		
		if (!$this->ListType == "myitems")
		{
			$this->ListType = "myitems";
			$this->LoadMyItems($attribs);
			$ret = $this->QueryItemCount;			
		}
		else
			$ret = $this->QueryItemCount;
		
		return $ret;
	}
		
	function CountHotItems($attribs)
	{		
		if (!$this->ListType == "hotitems")
		{
			$this->ListType = "hotitems";
			$this->LoadHotItems($attribs);
			$ret = $this->QueryItemCount;			
		}
		else
			$ret = $this->QueryItemCount;
		
		return $ret;
	}
	
	function CountNewItems($attribs)
	{		
		if (!$this->ListType == "newitems")
		{
			$this->ListType = "newitems";
			$this->LoadNewItems($attribs);
			$ret = $this->QueryItemCount;			
		}
		else
			$ret = $this->QueryItemCount;
		
		return $ret;
	}
	
	function CountPopItems($attribs)
	{		
		if (!$this->ListType == "popitems")
		{
			$this->ListType = "popitems";
			$this->LoadPopItems($attribs);
			$ret = $this->QueryItemCount;			
		}
		else
			$ret = $this->QueryItemCount;
		
		return $ret;
	}
		
	
	function CountSearchItems($attribs)
	{		
		if (!$this->ListType == "search")
		{
			$this->ListType = "search";
			$this->LoadSearchItems($attribs);
			$ret = $this->QueryItemCount;			
		}
		else
			$ret = $this->QueryItemCount;
		
		return $ret;
	}
	
	function SqlFavorites($attribs)
	{
        global $objSession, $objConfig, $objPermissions;

        $acl = $objSession->GetACLClause();
        $favtable = GetTablePrefix()."Favorites";
        $ltable = $this->SourceTable;
        $cattable = GetTablePrefix()."CategoryItems";
        $CategoryTable = GetTablePrefix()."Category";
        $ptable = GetTablePrefix()."PermCache";
     	   
        $where = "PortalUserId=".$objSession->Get("PortalUserId")." AND $ltable.Status=1";
        if($attribs["_today"])
        {
   	  		$today = mktime(0,0,0,date("m"),date("d"),date("Y"));                   	
	        $where .= " AND $favtable.Modified >= $today AND ItemTypeId=".$this->ItemType;          
        }
        $p = $this->BasePermission.".VIEW";
        
        $sql = "SELECT $ltable.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $favtable INNER JOIN $ltable ON ($favtable.ResourceId=$ltable.ResourceId) ";
        $sql .= $this->GetJoinedSQL($p,NULL,$where);


 	    $OrderBy = $this->QueryOrderByClause(TRUE,TRUE,TRUE);
        $sql .= " ".$OrderBy;
		return $sql;
	}
  
    function LoadFavorites($attribs)
    {
		global $objSession, $objCountCache;
		
		$sql = $this->SqlFavorites($attribs);
    	    
	    if($objSession->HasSystemPermission("DEBUG.LIST"))
              echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
        if($attribs["_shortlist"])
        {
            $this->PerPageVar = $this->PerPageShortVar; 
        }
        else 
          $this->PerPageVar = $this->PerPageVarLong;
        
        $CachedCount = $objCountCache->GetValue($this->CacheListType("favorites"),$this->ItemType,$this->CacheListExtraId("favorites"),(int)$attribs["_today"],3600);         
        if(!is_numeric($CachedCount))
        {
          $this->QueryItemCount = QueryCount($sql);
          $objCountCache->SetValue($this->CacheListType("favorites"),$this->ItemType,$this->CacheListExtraId("favorites"),(int)$attribs["_today"],$this->QueryItemCount);
        }
        else
         $this->QueryItemCount = (int)$CachedCount;
        
        return $this->Query_Item($sql);           
    }
    
    function SqlPickItems($attribs)
    {
       global $objSession, $objCatList;

       $catid = (int)getArrayValue($attribs,'_catid');
       $scope = (int)getArrayValue($attribs,'_scope');
	   //$JoinCats = (int)$attribs["_catinfo"] || $scope;	  
          	          
   	   $TableName = $this->SourceTable;
       if($scope)
       {
            if (!$catid) 
            {
               $catid = $objCatList->CurrentCategoryID();
            }                                            
            $where =  GetTablePrefix()."CategoryItems.CategoryId =".$catid." AND ".$TableName.".EditorsPick=1 AND ".$TableName.".Status=1";
       }
       else
       {
            $where = $TableName.".EditorsPick=1 AND ".$TableName.".Status=1 ";
            $catid=NULL;
       }
       if(getArrayValue($attribs,'_today'))
       {
   	  		$today = mktime(0,0,0,date("m"),date("d"),date("Y"));  
   	  		$where .= " AND ($TableName.CreatedOn>=$today)";
       }       
       $CategoryTable = GetTablePrefix()."Category";
 	   $sql = "SELECT $TableName.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $TableName ";
 	   $p = $this->BasePermission.".VIEW";
 	   $sql .= $this->GetJoinedSQL($p,$catid,$where);
 	   
       $OrderBy = $this->QueryOrderByClause(TRUE,TRUE,TRUE);
       $sql .= " ".$OrderBy; 	         
       return $sql;
    }    	
    
    function LoadPickItems($attribs)
    {
       global $objSession, $objCountCache;
       
       $sql = $this->SqlPickItems($attribs);     
       if($objSession->HasSystemPermission("DEBUG.LIST"))
            echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
            
        if($attribs["_shortlist"])
        {
            $this->PerPageVar = $this->PerPageShortVar; 
        }
        else 
          $this->PerPageVar = $this->PerPageVarLong;
                      
       $CachedCount = $objCountCache->GetValue($this->CacheListType("pick"),$this->ItemType,$this->CacheListExtraId("pick"),(int)getArrayValue($attribs,'_today'),3600);            
       if(!is_numeric($CachedCount))
       {
 	     $this->QueryItemCount= QueryCount($sql);
         $objCountCache->SetValue($this->CacheListType("pick"),$this->ItemType,$this->CacheListExtraId("pick"),(int)getArrayValue($attribs,'_today'),$this->QueryItemCount);
       }
       else
         $this->QueryItemCount=$CachedCount;

       return $this->Query_Item($sql);  	   
    }
    
    function SqlMyItems($attribs= array())
    {
        global $objSession;

		$TableName = $this->SourceTable;
 		$where =  " ".$TableName.".Status>-1 AND ".$TableName.".CreatedById=".$objSession->Get("PortalUserId");
        if(getArrayValue($attribs,'_today'))
        {
   	  		$today = mktime(0,0,0,date("m"),date("d"),date("Y"));  
   	  		$where .= " AND ($TableName.CreatedOn>=$today)";
        }
 		$CategoryTable = GetTablePrefix()."Category"; 	   
 		$sql = "SELECT $TableName.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $TableName ";
 	    $p = $this->BasePermission.".VIEW";
 	    $sql .= $this->GetJoinedSQL($p,null,$where); // maybe null should be replaced by some CategoryId
 	        	    
        $OrderBy = $this->QueryOrderByClause(TRUE,TRUE,TRUE);
        $sql .= " ".$OrderBy; 	         
	
        return $sql;
    }    
    
    function LoadMyItems($attribs=array())
    {        
    	global $objSession,$objCountCache;              
    	$sql = $this->SqlMyItems($attribs);
        if($objSession->HasSystemPermission("DEBUG.LIST"))
              echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
        if($attribs["_shortlist"])
        {
            $this->PerPageVar = $this->PerPageShortVar; 
        }
        else 
          $this->PerPageVar = $this->PerPageVarLong; 		
 		               
       $CachedCount = $objCountCache->GetValue($this->CacheListType("myitems"),$this->ItemType,$this->CacheListExtraId("myitems"),(int)$attribs["_today"],3600);            
       if(!is_numeric($CachedCount))
       {
 	     $this->QueryItemCount= QueryCount($sql);
         $objCountCache->SetValue($this->CacheListType("myitems"),$this->ItemType,$this->CacheListExtraId("myitems"),(int)$attribs["_today"],$this->QueryItemCount);
       }
       else
         $this->QueryItemCount=$CachedCount;
 
        return $this->Query_Item($sql);  	   
    }    
    
    function SqlNewItems($attribs = array())
    {
       global $objSession, $objCatList;

       $catid = (int)$attribs["_catid"];
       $scope = (int)$attribs["_scope"];
       $show_since_last = (int)$attribs["_show_since_last"];
	   //$JoinCats = (int)$attribs["_catinfo"] || $scope;	  	  
         //echo "Last: $scope<br><br>";
   	   $TableName = $this->SourceTable;
	   if($attribs["_today"])
       {
   	  		$cutoff = mktime(0,0,0,date("m"),date("d"),date("Y")); 
       }
       else
       {
       	  if($scope)
       	  {
            if (!$catid) 
            {
               $catid = $objCatList->CurrentCategoryID();
            } 
            if (!$show_since_last) {
         		$cutoff = $this->GetNewValue($catid);
            }
            else {            	
            	$cutoff = $scope;
            }
       	  }
       	  else
       	    $cutoff = $this->GetNewValue();
       }
       if($scope)
       {
            if (!$catid) 
            {
               $catid = $objCatList->CurrentCategoryID();
            }           	  	                                        
            
            if (!$show_since_last) {
            	$where =  "CategoryId =".$catid." AND ((".$TableName.".CreatedOn >=".$cutoff." AND ".$TableName.".NewItem != 0) OR ".$TableName.".NewItem=1 ) AND ".$TableName.".Status=1 ";            
            }
            else {
            	$where =  $TableName.".CreatedOn >=".$cutoff." AND ".$TableName.".Status=1 ";            
            }
       }
       else
       {
            $where =  "((".$TableName.".CreatedOn >=".$this->GetNewValue()." AND ".$TableName.".NewItem != 0) OR ".$TableName.".NewItem=1 ) AND ".$TableName.".Status=1 ";
       }

       $CategoryTable = GetTablePrefix()."Category";
 	   $sql = "SELECT $TableName.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $TableName ";
 	   $p = $this->BasePermission.".VIEW";
 	   $sql .= $this->GetJoinedSQL($p,$CatUd,$where);
 	   
       $OrderBy = $this->QueryOrderByClause(TRUE,TRUE,TRUE);
       $sql .= " ".$OrderBy;  
       //echo $sql;       
       return $sql;
    }

    function LoadNewItems($attribs)
    {
		global $objSession,$objCountCache;
		
		$sql = $this->SqlNewItems($attribs);
		
        if($objSession->HasSystemPermission("DEBUG.LIST"))
              echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
        if($attribs["_shortlist"])
        {
            $this->PerPageVar = $this->PerPageShortVar; 
        }
        else 
          $this->PerPageVar = $this->PerPageVarLong;
                        
       $CachedCount = $objCountCache->GetValue($this->CacheListType("new"),$this->ItemType,$this->CacheListExtraId("new"),(int)$attribs["_today"],3600);            
       if(!is_numeric($CachedCount))
       {
 	     $this->QueryItemCount= QueryCount($sql);
         $objCountCache->SetValue($this->CacheListType("new"),$this->ItemType,$this->CacheListExtraId("new"),(int)$attribs["_today"],$this->QueryItemCount);
       }
       else
         $this->QueryItemCount=$CachedCount;    
         
         
       return $this->Query_Item($sql);  	   
    }    

    function SqlPopItems($attribs)
    {
       global $objSession, $objCatList;

       $catid = (int)$attribs["_catid"];
       $scope = (int)$attribs["_scope"];
	   //$JoinCats = (int)$attribs["_catinfo"] || $scope;	  	   
                 
   	   $TableName = $this->SourceTable;

       if($scope)
       {
            if (!$catid) 
            {
               $catid = $objCatList->CurrentCategoryID();
            }   
            $where =  "CategoryId =".$catid." AND ((".$TableName.".Hits >=".$this->GetLinkPopValue()." AND ".$TableName.".PopItem !=0) OR ".$TableName.".PopItem=1) AND ".$TableName.".Status=1";
       }
       else       	
       {
             $where =  "((".$TableName.".CachedRating >=".$this->GetPopValue()." AND ".$TableName.".PopItem !=0 ) OR ".$TableName.".PopItem=1) AND ".$TableName.".Status=1 ";
             
       		$where =  "((".$TableName.".Hits >=".$this->GetPopValue()." AND ".$TableName.".PopItem !=0) OR ".$TableName.".PopItem=1) AND ".$TableName.".Status=1 ";
       }
        if($attribs["_today"])
        {
   	  		$today = mktime(0,0,0,date("m"),date("d"),date("Y"));  
   	  		$where .= " AND ($TableName.CreatedOn>=$today)";
        }        
       $CategoryTable = GetTablePrefix()."Category";
 	   $sql = "SELECT $TableName.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $TableName ";
 	   $p = $this->BasePermission.".VIEW";
 	   $sql .= $this->GetJoinedSQL($p,$catid,$where);
 	   
 	   $OrderBy = $this->QueryOrderByClause(TRUE,TRUE,TRUE);
       $sql .= " ".$OrderBy;
       
    	return $sql;
    }
    
    function LoadPopItems($attribs)
    {
       global $objSession,$objCountCache;
       $sql = $this->SqlPopItems($attribs);
            
       if($objSession->HasSystemPermission("DEBUG.LIST"))
              echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
        if($attribs["_shortlist"])
        {
            $this->PerPageVar = $this->PerPageShortVar; 
        }
        else 
          $this->PerPageVar = $this->PerPageVarLong;
                        
       $CachedCount = $objCountCache->GetValue($this->CacheListType("pop"),$this->ItemType,$this->CacheListExtraId("pop"),(int)$attribs["_today"],3600);            
       if(!is_numeric($CachedCount))
       {
 	     $this->QueryItemCount= QueryCount($sql);
         $objCountCache->SetValue($this->CacheListType("pop"),$this->ItemType,$this->CacheListExtraId("pop"),(int)$attribs["_today"],$this->QueryItemCount);
       }
       else
         $this->QueryItemCount=$CachedCount;
        
       return $this->Query_Item($sql);  	   
    }    

    function SqlHotItems($attribs)
    {
       global $objSession, $objCatList;

       $catid = (int)$attribs["_catid"];
       $scope = (int)$attribs["_scope"];

//       $JoinCats = (int)$attribs["_catinfo"] || $scope;	 

        $TableName = $this->SourceTable;	
		  	
		$OrderBy = $TableName.".CachedRating DESC";       

        if($scope)
        {
            if (!$catid) 
            {
               $catid = $objCatList->CurrentCategoryID();
            }        
            $where =  "CategoryId =".$catid." AND ((".$TableName.".CachedRating >=".$this->GetHotValue()." AND ".$TableName.".PopItem !=0) OR ".$TableName.".PopItem=1) AND ".$TableName.".Status=1";
        }
        else
        {
            $where =  "((".$TableName.".CachedRating >=".$this->GetPopValue()." AND ".$TableName.".PopItem !=0 ) OR ".$TableName.".PopItem=1) AND ".$TableName.".Status=1 ";
        }
        
        if($attribs["_today"])
        {
   	  		$today = mktime(0,0,0,date("m"),date("d"),date("Y"));  
   	  		$where .= " AND ($TableName.CreatedOn>=$today)";
        }        
        $CategoryTable = GetTablePrefix()."Category";
 	    $sql = "SELECT $TableName.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $TableName ";
 	    $p = $this->BasePermission.".VIEW";
 	    $CatId = !$scope? NULL : $catid; 	    
 	    $sql .= $this->GetJoinedSQL($p,$CatId,$where);
 	   
        if(strlen($OrderBy))
            $sql .= " ORDER BY $OrderBy "; 	    
                 
    	return $sql;
    }
    
    function LoadHotItems($attribs)
    {
        global $objSession,$objCountCache;    
    	
        $sql = $this->SqlHotItems($attribs);
        if($objSession->HasSystemPermission("DEBUG.LIST"))
              echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
              
        if($attribs["_shortlist"])
        {
            $this->PerPageVar = $this->PerPageShortVar; 
        }
        else 
          $this->PerPageVar = $this->PerPageVarLong;   
                     
       $CachedCount = $objCountCache->GetValue($this->CacheListType("hot"),$this->ItemType,$this->CacheListExtraId("hot"),(int)$attribs["_today"], 0);            
       if(!is_numeric($CachedCount))
       {
 	     $this->QueryItemCount= QueryCount($sql);
         $objCountCache->SetValue($this->CacheListType("hot"),$this->ItemType,$this->CacheListExtraId("hot"),(int)$attribs["_today"],$this->QueryItemCount);
       }
       else
         $this->QueryItemCount=$CachedCount;
        
       return $this->Query_Item($sql);  	       	
    }
    
    function SqlSearchItems($attribs = array())
    {
        global $objConfig, $objItemTypes, $objSession, $objPermissions, $CountVal;

        $acl = $objSession->GetACLClause();
        $this->Clear();
        //$stable = "ses_".$objSession->GetSessionKey()."_Search";
        $stable = $objSession->GetSearchTable();
        $ltable = $this->SourceTable;
        $catitems = GetTablePrefix()."CategoryItems";
        $cattable = GetTablePrefix()."Category";
        $ptable = GetTablePrefix()."PermCache";
        $p = $this->BasePermission.".VIEW";
        $i = new $this->classname();
        
        $sql =  "SELECT $cattable.CategoryId,$cattable.CachedNavbar,$ltable.*, Relevance FROM $stable ";
        $sql .= "INNER JOIN $ltable ON ($stable.ItemId=$ltable.".$i->id_field.") ";
        
        $where = "ItemType=".$this->ItemType." AND $ltable.Status=1";
        
        $load_multiple = $objConfig->Get("Search_ShowMultiple_".$attribs['multiple']);
        $LoadOnlyPrimary = true;
        
        if ($load_multiple == 1) {
        	$LoadOnlyPrimary = false;
        }
        
        $sql .= $this->GetJoinedSQL($p,NULL,$where, $LoadOnlyPrimary);               
        $sql .= " ORDER BY EdPick DESC,Relevance DESC ";
        
        $tmp = $this->QueryOrderByClause(FALSE,TRUE,TRUE);
        $tmp = substr($tmp,9);
        if(strlen($tmp))
        {
        	$sql .= ", ".$tmp." ";
        }
        //echo "SQL Search Items: $sql<br><br>";
		return $sql;    	
    }
        
    function LoadSearchItems($attribs = array())
    {
		global $CountVal, $objSession;
        //echo "Loading <b>".get_class($this)."</b> Search Items<br>";
		$sql = $this->SqlSearchItems($attribs);
        //echo "$sql<br>";
        $this->Query_Item($sql);
        $Keywords = GetKeywords($objSession->GetVariable("Search_Keywords"));
        //echo "SQL Loaded ItemCount (<b>".get_class($this).'</b>): '.$this->NumItems().'<br>';
        for($i = 0; $i < $this->NumItems(); $i++)
        {
          $this->Items[$i]->Keywords = $Keywords;
        }
        if(is_numeric($CountVal[$this->ItemType]))
        {
          $this->QueryItemCount = $CountVal[$this->ItemType];
          //echo "CACHE: <pre>"; print_r($CountVal); echo "</pre><BR>";
        }
        else
        {
          $this->QueryItemCount = QueryCount($sql);
          //echo "<b>SQL</b>: ".$sql."<br><br>";
          $CountVal[$this->ItemType] = $this->QueryItemCount;
        }
                
    }
        
    function PasteFromClipboard($TargetCat,$NameField="")
    {
      global $objSession,$objCatList;
	
      $clip = $objSession->GetVariable("ClipBoard");
      if(strlen($clip))
      {
          $ClipBoard = ParseClipboard($clip);
          $IsCopy = (substr($ClipBoard["command"],0,4)=="COPY") || ($ClipBoard["source"] == $TargetCat);

          $item_ids = explode(",",$ClipBoard["ids"]);
          for($i=0;$i<count($item_ids);$i++)
          {              
              $item = $this->GetItem($item_ids[$i]);
              if(!$IsCopy) // paste to other category then current
              {   
                  $item->MoveToCategory($ClipBoard["source"],$TargetCat);                                                   
                  $clip = str_replace("CUT","COPY",$clip);
                  $objSession->SetVariable("ClipBoard",$clip);
              }
              else
              {              
                    $item->CopyToNewResource($TargetCat,$NameField); // create item copy, but with new ResourceId
                    $item->AddToCategory($TargetCat);
                    UpdateCategoryCount($item->type,$TargetCat);
              
              }
          }
      }
    }
    
    function AdminPrintItems($template)
	{
	    // prints item listing for admin (browse/advanced view) tabs
	    $o = '<table border="0" cellspacing="2" width="100%"><tbody><tr>';
	
		$i = 1;
	    
	    $topleft		=	0;
	    $topright		=	0;
	    $rightcount		=	0;
	    $total_items	=	$this->NumItems();
	    $topleft		=	ceil($total_items / 2);
	    $topright		=	$total_items - $topleft;
	  
	    for($x = 0; $x < $topleft; $x++) 
	    {
	        //printingleft
	        $item = $this->Items[$x];
			if ($i > 2)
			{
				$o .= "</tr>\n<tr>";
				$i = 1;
			}
			$o .= $item->AdminParseTemplate($template);
			$i++;
	        
	        //printingright
	        if ($rightcount < $topright && ( ($x + $topleft) < $total_items) ) 
	        {
	            $item = $this->Items[ $x + $topleft ];
				if ($i > 2)
				{	
				    $o.="</tr>\n<tr>";
				    $i = 1;
				}
				$o .= $item->AdminParseTemplate($template);
				$i++;
	            $rightcount++;
	        }
	    }
		$o .= "\n</tr></tbody></table>\n";   

		return $o;
	}
    
}

// -------------- NEW CLASSES -----------------------

class DBList {
	
	// table related attributes
	var $db = null;
	var $table_name = '';
	var $LiveTable = '';
	var $EditTable = '';
	
	
	// record related attributes
	var $records = Array();
	var $record_count = 0;
	var $cur_rec = -1; // "-1" means no records, or record index otherwise
	
	// query related attributes
	var $SelectSQL = "SELECT * FROM %s";
	
	function DBList()
	{
		// use $this->SetTable('live', 'table name');
		// in inherited constructors to set table for list
		$this->db =&GetADODBConnection();	
	}
	
	function SetTable($action, $table_name = null)
    {
    	// $action = {'live', 'restore','edit'}
    	switch($action)
    	{
    		case 'live': 
    			$this->LiveTable = $table_name;
    			$this->table_name = $this->LiveTable;
    			break;
    		case 'restore': 
    			$this->table_name = $this->LiveTable; 
    			break;
    		case 'edit':
    			global $objSession;
    			$this->table_name = $objSession->GetEditTable($this->LiveTable);
    			break;
    	}
    }
	
	function Clear()
	{
		// no use of this method at a time :)
		$this->records = Array();
		$this->record_count = 0;
		$this->cur_rec = -1;	
	}
	
	function Query()
	{
		// query list	
		$sql = sprintf($this->SelectSQL, $this->table_name);
		echo "SQL: $sql<br>";
		$rs =& $this->db->Execute($sql);
		
		if( $this->db->ErrorNo() == 0 )
		{
			$this->records = $rs->GetRows();
			$this->record_count = count($this->records);
			//$this->cur_rec = $this->record_count ? 0 : -1;
		}
		else
			return false;
	}
	
	function ProcessList($callback_method)
	{
		// process list using user-defined method called
		// with one parameter - current record fields 
		// (associative array)
		if($this->record_count > 0)
		{
			$this->cur_rec = 0;
			while($this->cur_rec < $this->record_count)
			{
				if( method_exists($this, $callback_method) )
					$this->$callback_method( $this->GetCurrent() );
				$this->cur_rec++;	
			}
		}
	}
	
	function &GetCurrent()
	{
		// return currently processed record (with change ability)
		return ($this->cur_rec != -1) ? $this->records[$this->cur_rec] : false;
	}
	
	function GetDBField($field_name)
	{
		$rec =& $this->GetCurrent();
		return is_array($rec) && isset($rec[$field_name]) ? $rec[$field_name] : false;
	}
}


?>