1   <?php
  2  
  3   define('TYPE_TOPIC', 3);
  4   define('Locked', 3);
  5  
  6   RegisterPrefix("clsTopic","topic","in-bulletin/topic.php");
  7  
  8   class clsTopic extends clsCatItem
  9   {
  10       function clsTopic($TopicId=NULL)
  11       {
  12           global $objSession;
  13  
  14           $this->clsCatItem(TRUE);
  15           $this->tablename=GetTablePrefix()."Topic";
  16           $this->type=TYPE_TOPIC;
  17           $this->BasePermission="TOPIC";
  18           $this->Prefix = 'bb';
  19           $this->id_field = "TopicId";
  20           $this->TagPrefix = "topic";
  21           $this->TitleField = 'TopicText';
  22           if(isset($TopicId))
  23               $this->LoadFromDatabase($TopicId);
  24           if($objSession->HasSystemPermission("DEBUG.ITEM"))
  25           {
  26               $this->SetDebugLevel(1);
  27           }
  28  
  29           $this->OpenTagVar = "Topic_Highlight_OpenTag";
  30           $this->CloseTagVar = "Topic_Highlight_CloseTag";
  31       }
  32  
  33       function ClearCacheData()
  34       {
  35                   DeleteModuleTagCache('inbulletin');
  36           /*       $cats = explode(",",$this->CategoryMemberList());
  37          if(is_array($cats))
  38          {
  39            foreach($cats as $c)
  40            {
  41              if(is_numeric($c))
  42              {
  43                $evar = "'%:m".$c."%'";
  44                DeleteTagCache("bb_topic_list","",$evar);
  45                DeleteTagCache("bb_topic_more","",$evar);
  46              }
  47            }
  48          }
  49          DeleteTagCache("bb_topic_modified%","");
  50          DeleteTagCache("TopicPopValue","","");
  51          DeleteTagCache("TopicHotValue","","");
  52          DeleteTagCache("TopicNewValue","","");*/
  53       }
  54  
  55       function Validate()
  56       {
  57           global $Errors;
  58  
  59           $dataValid = true;
  60  
  61  
  62           if(!strlen($this->Get("TopicText")))
  63           {
  64               $objSession->AddError("error.fieldIsRequired",'TopicText',"","",get_class($this),"Validate");
  65               $dataValid = false;
  66           }
  67  
  68           if(!(int)($this->Get("OwnerId")))
  69           {
  70               $Errors->AddError("error.fieldIsRequired",'Owner',"","",get_class($this),"Validate");
  71               $dataValid = false;
  72           }
  73           return $dataValid;
  74       }
  75  
  76  
  77       function Update($UpdatedBy=NULL,$modificationDate=null)
  78       {
  79           parent::Update($UpdatedBy,$modificationDate);
  80           if($this->tablename==GetTablePrefix()."Topic")
  81           {
  82               $this->ClearCacheData();
  83           }
  84       }
  85  
  86       function Create()
  87       {
  88           parent::Create();
  89           if($this->tablename==GetTablePrefix()."Topic")
  90           {
  91               $this->ClearCacheData();
  92               DeleteTagCache("m_itemcount","Topic%");
  93           }
  94       }
  95  
  96       function Delete()
  97       {
  98           global $objPostingList, $objCatList;
  99  
  100           $PostCount = $this->Get("Posts");
  101           $objPostingList->DeleteTopicPosts($this->Get("TopicId"));
  102           $CategoryId = $this->Get("CategoryId");
  103           if(!is_numeric($CategoryId))
  104                    $CategoryId = $objCatList->CurrentCategoryID();
  105  
  106           if($this->tablename==GetTablePrefix()."Topic")
  107           {
  108               $this->ClearCacheData();
  109               DeleteTagCache("m_itemcount","Topic%");
  110  
  111               if($this->Get("NotifyOwnerOnChanges"))
  112                   {
  113                   $this->SendUserEventMail("TOPIC.DELETE",$this->Get('OwnerId') );
  114                   }
  115                   $this->SendAdminEventMail("TOPIC.DELETE");
  116           }
  117           parent::Delete();
  118  
  119           $this->refreshLastUpdate($CategoryId);
  120  
  121           $this->UpdateCategoryPostCount();
  122       }
  123  
  124       function UpdateModified($UserId)
  125           {
  126                   $this->Set(array("Modified", "ModifiedById"), array(adodb_mktime(), $UserId));
  127                   $this->Update();
  128           }
  129  
  130           function UpdateNumPosts()
  131           {
  132                   global $objSession;
  133  
  134                   $sql = "SELECT COUNT(PostingId) as PostCount FROM ".GetTablePrefix()."Posting WHERE TopicId=" . $this->Get("TopicId");
  135                   $result = $this->adodbConnection->Execute($sql);
  136  
  137                   if($result && !$result->EOF)
  138                   {
  139               $sql = "UPDATE ".$this->tablename." SET Posts=".$result->fields["PostCount"]." WHERE TopicId=" . $this->Get("TopicId");
  140                           $result = $this->adodbConnection->Execute($sql);
  141                           if ($result === false)
  142                           {
  143                                   $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"UpdateNumPosts");
  144                                   return false;
  145                           }
  146                   }
  147           }
  148  
  149       function SetNewItem()
  150       {
  151           global $objConfig;
  152  
  153           $value = $this->Get("CreatedOn");
  154  
  155           $cutoff = adodb_date("U") - ($objConfig->Get("Topic_NewDays") * 86400);
  156           $this->IsNew = FALSE;
  157           if($value>$cutoff)
  158             $this->IsNew = TRUE;
  159           return $this->IsNew;
  160       }
  161  
  162       function SetPopItem()
  163       {
  164           global $objConfig, $objTopicList;
  165  
  166           $cutoff = $objTopicList->GetPopValue();
  167           if($cutoff > 0)
  168           {
  169             $this->IsPop = FALSE;
  170             if($this->Get('Posts') >= $cutoff)
  171                     {
  172               $this->IsPop = TRUE;
  173                     }
  174           }
  175           else
  176               $this->IsPop = FALSE;
  177           return $this->IsPop;
  178       }
  179  
  180       function SetHotItem()
  181       {
  182           global $objConfig, $objTopicList;
  183  
  184           $this->IsHot = FALSE;
  185           $cutoff = $objTopicList->GetHotValue();
  186           if($cutoff>0)
  187           {
  188               if($this->Get("Views") >= $cutoff)
  189                 $this->IsHot = TRUE;
  190           }
  191           return $this->IsHot;
  192       }
  193  
  194           function Approve()
  195           {
  196             $this->Set("Status", 1);
  197             $this->Update();
  198         $this->SendUserEventMail("TOPIC.APPROVE",$this->Get("OwnerId"));
  199         $this->SendAdminEventMail("TOPIC.APPROVE");
  200           }
  201  
  202       function Deny()
  203       {
  204           $this->Set("Status", 0);
  205           $this->Update();
  206           $this->SendUserEventMail("TOPIC.DENY",$this->Get("OwnerId"));
  207           $this->SendAdminEventMail("TOPIC.DENY");
  208       }
  209  
  210       function LoadFromDatabase($Id)
  211       {
  212                   global $Errors;
  213  
  214           if(!isset($Id))
  215           {
  216               $Errors->AddError("error.AppError",NULL,'Internal error: LoadFromDatabase id',"",get_class($this),"LoadFromDatabase");
  217               return false;
  218           }
  219           if($Id>0)
  220           {
  221             $sql = sprintf("SELECT * FROM ".$this->tablename." WHERE ".$this->IdField()." = '%s'",$Id);
  222             $result = $this->adodbConnection->Execute($sql);
  223             if ($result === FALSE)
  224             {
  225               $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"LoadFromDatabase");
  226               return FALSE;
  227             }
  228  
  229             $data = $result->fields;
  230  
  231             $this->SetFromArray($data);
  232             return TRUE;
  233           }
  234           else
  235               return FALSE;
  236       }
  237       function LoadFromResourceId($Id)
  238       {
  239           global $objSession, $Errors;
  240           if(!isset($Id))
  241           {
  242               $Errors->AddError("error.AppError",NULL,'Internal error: LoadFromDatabase id',"",get_class($this),"LoadFromResourceId");
  243               return false;
  244           }
  245           $sql = sprintf("SELECT * FROM ".$this->tablename." WHERE ResourceId = '%s'",$Id);
  246           $result = $this->adodbConnection->Execute($sql);
  247           if ($result === false)
  248           {
  249               $Errors->AddError("error.DatabaseError",NULL,$adodbConnection->ErrorMsg(),"",get_class($this),"LoadFromResourceId");
  250               return false;
  251           }
  252           $data = $result->fields;
  253           if(is_array($data))
  254               $this->SetFromArray($data);
  255       }
  256  
  257  
  258           function GetPostsSince($time_stamp)
  259           {
  260                   global $Errors;
  261  
  262                   $Id = $this->Get("TopicId"); //get cur cat id
  263                   settype($time_stamp,"integer");
  264                   $sql = "SELECT count(PostingId) as pcount FROM ".GetTablePrefix()."Posting WHERE TopicId = $Id AND Posting.ModifiedOn >= $time_stamp ";
  265                   $result = $this->adodbConnection->Execute($sql);
  266                   if($result && !$result->EOF)
  267                           return $result->fields["pcount"];
  268                   else
  269                   {
  270                           $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"",get_class($this),"GetPostsSince");
  271                           return false;
  272                   }
  273  
  274           }
  275  
  276           function GetPosts()
  277           {
  278                   global $Errors;
  279  
  280   /*        if(!is_numeric($this->Get("Posts"))<1)
  281           {
  282                     $Id = $this->Get("TopicId"); //get cur cat id
  283  
  284                     $sql = "SELECT count(PostingId) FROM ".GetTablePrefix()."Posting WHERE TopicId = $Id";
  285                     $result = $this->adodbConnection->Execute($sql);
  286                     if($result && !$result->EOF)
  287                           $this->Set("Posts",$result->fields[0]);
  288                     else
  289                     {
  290                           $Errors->AddError("error.DatabaseError",NULL,$this->adodbConnection->ErrorMsg(),"","clsTopic","GetPosts");
  291                           return false;
  292                     }
  293           }*/
  294           return $this->Get("Posts");
  295           }
  296  
  297       function StatusIcon()
  298       {
  299           global $rootURL;
  300  
  301          $ret = $rootURL."/in-bulletin/admin/images/";
  302  
  303          switch($this->Get("Status"))
  304          {
  305            case STATUS_DISABLED:
  306              $ret .= "icon16_topic_disabled.gif";
  307              break;
  308            case STATUS_PENDING:
  309              $ret .= "icon16_topic_pending.gif";
  310              break;
  311            case STATUS_ACTIVE:
  312              $img = "icon16_topic.gif";
  313              if($this->IsPopItem())
  314                  $img = "icon16_topic_top.gif";
  315              if($this->IsHotItem())
  316                  $img = "icon16_topic_hot.gif";
  317              if($this->IsNewItem())
  318                  $img = "icon16_topic_new.gif";
  319              if($this->Is("EditorsPick"))
  320                  $img = "icon16_topic_pick.gif";
  321              $ret .= $img;
  322              break;
  323          }
  324          return $ret;
  325       }
  326  
  327       function ItemURL($Template=NULL,$SetCat=FALSE,$Action=NULL)
  328       {
  329                   global $var_list_update,$var_list,$bb_var_list_update,$m_var_list_update;
  330  
  331                   $url_params = Array();
  332                   $var_list_update["t"] = $Template ? $Template : $var_list["t"];
  333  
  334   //        if($SetCat || (int)$this->Get("CategoryId")>0)
  335   //        {
  336              $cat = $this->Get("CategoryId");
  337              if(!is_numeric($cat))
  338                $cat = $this->GetPrimaryCategory();
  339               $m_var_list_update["cat"] = $cat;
  340   //        }
  341  
  342           $bb_var_list_update["top"] = $this->Get("TopicId");
  343           $bb_var_list_update["pp"] = 1;
  344  
  345           if( isset($Action) && $Action ) $url_params['Action'] = $Action;
  346           $ret = HREF_Wrapper('', $url_params);
  347  
  348           unset($m_var_list_update["cat"],$bb_var_list_update["top"],$bb_var_list_update["tp"],$bb_var_list_update["pp"], $var_list_update["t"]);
  349           return $ret;
  350       }
  351  
  352       function ParseObject($element)
  353       {
  354           global $objConfig, $objSession, $objUsers, $objCatList, $var_list_update, $var_list,
  355                  $bb_var_list_update, $m_var_list_update,$objCensorList;
  356  
  357           //print_pre($element);
  358  
  359           $extra_attribs = ExtraAttributes($element->attributes);
  360           if(strtolower($element->name)==$this->TagPrefix)
  361           {
  362               $field = strtolower($element->attributes["_field"]);
  363               switch($field)
  364               {
  365  
  366                   /*
  367                   @field:topic.text
  368                   @description: Returns the topic title (or subject)
  369                   */
  370                   case "text":
  371                           $topic_text = inp_unescape($objCensorList->CensorText($this->Get("TopicText")));
  372                           $num_chars = $element->GetAttributeByName('_numchars');
  373                           if ($num_chars && strlen($topic_text) > $num_chars) {
  374                           $ret = substr($topic_text, 0, $num_chars)."...";
  375                     }
  376                     else {
  377                           $ret = $topic_text;
  378                     }
  379                     $ret = $this->HighlightText($ret);
  380                   break;
  381                   /*
  382                   @field:topic.replies
  383                   @description: Returns the number of posts for the topic (The first post is not counted)
  384                   */
  385                                   case "replies":
  386                                     $ret = $this->GetPosts() - 1;
  387                                   break;
  388                                   /*
  389                                   @field:topic.views
  390                                   @description: Returns the number of times the topic has been viewed
  391                                   */
  392                                   case "views":
  393                                           return round($this->Get("Views"));
  394                                   break;
  395                   /*
  396                   @field:topic.category
  397                   @description:Return a category field from the link's category
  398                   @attrib:_cattag::Category field to parse
  399                   */
  400  
  401               case "lastposter":
  402                   /*
  403                   @field:topic.lastposter
  404                   @description:Returns the login name of the last poster in this topic
  405                   */
  406                   if(strlen($this->Get("LastPoster")))
  407                   {
  408                       $ret = $this->Get("LastPoster");
  409                   }
  410                   else
  411                   {
  412                       $id = $this->Get("LastPostId");
  413                       if (!is_numeric($id)) {
  414                                                   $id = $this->GetLastPostId();
  415                       }
  416                      
  417                       if ($id) {
  418                         $post = new clsPosting($id);
  419                         if (is_object($post)) {
  420                           $ret = $post->Get('PosterAlias');
  421                           if (!$ret && ($post->Get('CreatedById') < 0)) {
  422                                   $ret = language('lu_Guest');
  423                           }
  424                         }
  425                       }
  426                   }
  427               break;
  428               case "lastpostdate":
  429                   /*
  430                                   @field:topic.lastpostdate
  431                                   @description:Returns the date/time a post was made to this topic
  432                                   @attrib:_tz:bool:Convert the date to the user's local time
  433                                   @attrib:_part::Returns part of the date.  The following options are available: month,day,year,time_24hr,time_12hr
  434                   */
  435                   $d = $this->Get("LastPostDate");
  436                   if (!$element->GetAttributeByName('_tz')) {
  437                           $element->SetAttributeByName('_tz', 'auto');
  438                   }
  439                   $ret = $this->ParseTimeStamp($d, $element->attributes);
  440               break;
  441                   /*
  442                                   @field:topic.image
  443                                   @description:Return an image associated with the topic
  444                                   @attrib:_primary:bool:If true, will return the default image if the requested image does not exist
  445                                   @attrib:_name::Return the image with this name
  446                                   @attrib:_thumbnail:bool:If true, return the thumbnail version of the image
  447                                   @attrib:_imagetag:bool:If true, returns a complete image tag. exta html attributes are passed to the image tag
  448                  */
  449               case "modifiedby":
  450                                   /*
  451                                   @field:topic.modifiedby
  452                                   @description:parse a user field of the user that last modified the topic
  453                                   @attrib:_usertag::User field to return (defaults to login ID)
  454                                   */
  455                   $field = $element->attributes["_usertag"];
  456                   if(!strlen($field))
  457                   {
  458                       $field = "user_login";
  459                   }
  460                   $u =& $objUsers->GetItem($this->Get("ModifiedById"));
  461                   $ret = $u->parsetag($field);
  462               break;
  463               case "owner":
  464                                   /*
  465                                   @field:topic.owner
  466                                   @description:parse a user field of the user that is the topic owner
  467                                   @attrib:_usertag::User field to return (defaults to login ID)
  468                                   */
  469                   $field = $element->attributes["_usertag"];
  470                   if(!strlen($field))
  471                   {
  472                       $field = "user_login";
  473                   }
  474                   $u =& $objUsers->GetItem($this->Get("OwnerId"));
  475                   $ret = $u->parsetag($field);
  476               break;
  477  
  478                   /*
  479                   @field:topic.custom
  480                   @description:Returns a custom field
  481                                   @attrib:_customfield::field name to return
  482                                   @attrib:_default::default value
  483                                   */
  484               case "date":
  485                   /*
  486                                   @field:topic.date
  487                                   @description:Returns the date/time the topic was created
  488                                   @attrib:_tz:bool:Convert the date to the user's local time
  489                                   @attrib:_part::Returns part of the date.  The following options are available: month,day,year,time_24hr,time_12hr
  490                   */
  491                   $d = $this->Get('CreatedOn');
  492                   if (!$element->GetAttributeByName('_tz')) {
  493                           $element->SetAttributeByName('_tz', 'auto');
  494                   }
  495                   $ret = $this->ParseTimeStamp($d,$element->attributes);
  496               break;
  497               case "modifieddate":
  498                   /*
  499                                   @field:link.modifieddate
  500                                   @description:Returns the date/time the topic was last modified
  501                                   @attrib:_tz:bool:Convert the date to the user's local time
  502                                   @attrib:_part::Returns part of the date.  The following options are available: month,day,year,time_24hr,time_12hr
  503                   */
  504                   $d = $this->Get('Modified');
  505                   if (!$element->GetAttributeByName('_tz')) {
  506                           $element->SetAttributeByName('_tz', 'auto');
  507                   }
  508                   $ret = $this->ParseTimeStamp($d,$element->attributes);
  509               break;
  510                   /*
  511                   @field:topic.fullpath
  512                   @description:The full category path of the item
  513                   */
  514               //break;
  515               case "locked":
  516                   /*
  517                   @field:topic.locked
  518                   @description: Returns a value if the topic is locked
  519                   @attrib:_text:lang:Language tag to display as the link text
  520                   @attrib:_plaintext:: Plain text to use instead of language tag
  521                   @attrib:image::Image URL to display
  522                   */
  523  
  524                   if($this->Get("TopicType")==0)
  525                   {
  526                     $text = $element->attributes["_text"];
  527                     if(!strlen($text))
  528                     {
  529                       $text = $element->attributes["_plaintext"];
  530                       if(!strlen($text))
  531                       {
  532                       if(strlen($element->attributes["_image"]))
  533                       {
  534                               $text = "<IMG SRC=\"".$element->attributes["_image"]."\" BORDER=\"0\" alt=\"\">";
  535                           }
  536                       }
  537                       $ret .= $text."</A>";
  538                     }
  539                     else
  540                       $ret .= language($text)."</A>";
  541                     if(!strlen($ret)) $ret = "locked";
  542                   }
  543                   else {
  544                           $ret = '';
  545                   }
  546  
  547                break;
  548                   /*
  549                   @field:topic.cat_link
  550                   @description:Returns a URL setting the topic to the current topic and the topic's category to the current category
  551                                   @attrib:_template:tpl:Template URL should point to
  552                   */
  553                   /*
  554                                   @field:topic.link
  555                                   @description:Returns a URL setting the topic to the current topic
  556                                   @attrib:_template:tpl:Template URL should point to
  557                                   */
  558               case "perm_link":
  559                                   /*
  560                                   @field:topic.perm_link
  561                                   @description: Returns a link to the current topic if permissions are set for the user
  562                                   @attrib:_permission::Comma-separated permission list to check, any one permission granted to the user will create the link
  563                                   @attrib:_system:bool:Set this to true if any one permission in the list is a system permission
  564                                   @attrib:_noaccess:tpl:Template to link to if access is denied
  565                                   @attrib:_template:tpl:Tempalte to link to if access is granted
  566                   @attrib:_text:lang:Language tag to display as the link text
  567                   @attrib:_plaintext:: Plain text to use instead of language tag
  568                   @attrib:image::Image URL to display in the anchor tag
  569                                   */
  570                   $p = $element->attributes["_permission"];
  571                   $sys = $element->attributes["_system"];
  572                   $cat = $this->Get("CategoryId");
  573                   if(!is_numeric($cat))
  574                       $cat = $this->GetPrimaryCategory();
  575  
  576                   $HasPerm = $objSession->HasCatPermInList($p,$cat, $sys);
  577                   if(!$HasPerm && strlen($element->attributes["_noaccess"])>0)
  578                   {
  579                       $t = $element->attributes["_noaccess"];
  580                       $ret = $this->ItemURL($t,FALSE,"");
  581                   }
  582                   if($HasPerm)
  583                   {
  584                       $t = $element->attributes["_template"];
  585                       $ret = "<A HREF=\"".$this->ItemURL($t)."\">";
  586                       $text = $element->attributes["_text"];
  587                       if(!strlen($text))
  588                       {
  589                           $text = $element->attributes["_plaintext"];
  590                           if(!strlen($text))
  591                           {
  592                               if(strlen($element->attributes["_image"]))
  593                               {
  594                                   $text = "<IMG SRC=\"".$element->attributes["_image"]."\" BORDER=\"0\" alt=\"\">";
  595                               }
  596                           }
  597                           $ret .= $text."</A>";
  598                       }
  599                       else
  600                         $ret .= language($text)."</A>";
  601                   }
  602                   else
  603                           $ret = '';
  604               break;
  605               case "link_lock":
  606                   /*
  607                   @field:topic.link_lock
  608                   @description: Returns a link to lock or unlock the topic. A complete anchor tag is returned, and the tag class is set to 'topic_reply'
  609                   @attrib:_template:tpl:Template link should point to
  610                   @attrib:_text:lang:Language tag to display as the link text
  611                   @attrib:_plaintext:: Plain text to use instead of language tag
  612                   @attrib:image::Image URL to display in the anchor tag
  613                   */
  614                   $cat = $this->Get("CategoryId");
  615                   if(!is_numeric($cat))
  616                       $cat = $this->GetPrimaryCategory();
  617  
  618                   if($objSession->HasCatPermission("TOPIC.LOCK",$cat))
  619                   {
  620                       $t = $element->attributes["_template"];
  621                       if(strlen($t))
  622                       {
  623                           $var_list_update["t"] = $t;
  624                       }
  625                       else
  626                           $var_list_update["t"] = $var_list["t"];
  627  
  628                       $bb_var_list_update["top"] = $this->Get("TopicId");
  629                       if($this->Get("TopicType")==1)
  630                       {
  631                           $ret = "<A HREF=\"".HREF_Wrapper('', Array('Action' => 'bb_lock_topic') )."\">";
  632                       }
  633                       else
  634                           $ret = "<A HREF=\"".HREF_Wrapper('', Array('Action' => 'bb_unlock_topic') )."\">";
  635                       $text = $element->attributes["_text"];
  636                       if(!strlen($text))
  637                       {
  638                           $text = $element->attributes["_plaintext"];
  639                           if(!strlen($text))
  640                           {
  641                               if(strlen($element->attributes["_image"]))
  642                               {
  643                                   $text = "<IMG SRC=\"".$element->attributes["_image"]."\" BORDER=\"0\" alt=\"\">";
  644                               }
  645                           }
  646                           $ret .= $text."</A>";
  647                       }
  648                       else
  649                         $ret .= language($text)."</A>";
  650                   }
  651                   else
  652                       $ret = "";
  653                   unset($bb_var_list_update["top"], $m_var_list_update["cat"],$var_list_update["t"]);
  654               break;
  655  
  656               case "link_delete":
  657                   /*
  658                   @field:topic.link_delete
  659                   @description: Returns a link to delete the topic.
  660                   @attrib:_template:tpl:Template link should point to
  661                   @attrib:_text:lang:Language tag to display as the link text
  662                   @attrib:_plaintext:: Plain text to use instead of language tag
  663                   @attrib:image::Image URL to display in the anchor tag
  664                   */
  665                   $cat = $this->Get("CategoryId");
  666                   if(!is_numeric($cat))
  667                       $cat = $this->GetPrimaryCategory();
  668  
  669                   $OwnerPerm = ($objSession->HasCatPermission("TOPIC.OWNER.DELETE", $cat) &&
  670                                $objSession->Get("PortalUserId")==$this->Get("OwnerId"));
  671  
  672                   if($objSession->HasCatPermission("TOPIC.DELETE",$cat) || $OwnerPerm)
  673                   {
  674                       $bb_var_list_update["top"] = $this->Get("TopicId");
  675                       $m_var_list_update["cat"] = $cat;
  676                       $ret = "<A CLASS=\"topic_delete\" HREF=\"".HREF_Wrapper('', Array('Action' => 'bb_topic_delete') ) ."\">";
  677                       $text = $element->attributes["_text"];
  678                       if(!strlen($text))
  679                       {
  680                           $text = $element->attributes["_plaintext"];
  681                           if(!strlen($text))
  682                           {
  683                               if(strlen($element->attributes["_image"]))
  684                               {
  685                                   $text = "<IMG SRC=\"".$element->attributes["_image"]."\" BORDER=\"0\" alt=\"\">";
  686                               }
  687                           }
  688                           $ret .= $text."</A>";
  689                       }
  690                       else
  691                         $ret .= language($text)."</A>";
  692                   }
  693                   else
  694                       $ret = "";
  695  
  696                   unset($bb_var_list_update["top"], $m_var_list_update["cat"]);
  697               break;
  698  
  699               case "link_edit":
  700                   /*
  701                   @field:topic.link_edit
  702                   @description: Rturns a link edit the topic. A complete anchor tag is returned, and the tag class is set to 'topic_reply'
  703                   @attrib:_template:tpl:Template link should point to
  704                   @attrib:_text:lang:Language tag to display as the link text
  705                   @attrib:_plaintext:: Plain text to use instead of language tag
  706                   @attrib:image::Image URL to display in the anchor tag
  707                   */
  708                   $cat = $this->Get("CategoryId");
  709                   if (!is_numeric($cat)) {
  710                           $cat = $this->GetPrimaryCategory();
  711                   }
  712                      
  713                                   $perms[1] = $objSession->HasCatPermission('TOPIC.MODIFY', $cat) || $objSession->HasCatPermission("TOPIC.MODIFY.PENDING", $cat);
  714                   $perms[2] = $objSession->Get("PortalUserId") == $this->Get("OwnerId") && $objSession->HasCatPermission("TOPIC.OWNER.MODIFY", $cat);
  715                   $perms[3] = $objSession->Get("PortalUserId") == $this->Get("OwnerId") && $objSession->HasCatPermission("TOPIC.OWNER.MODIFY.PENDING", $cat);
  716                   
  717                  if ( ($perms[1] || $perms[2] || $perms[3]) && ($this->Get("TopicType") == 1) ) {
  718                  
  719                       $bb_var_list_update["top"] = $this->Get("TopicId");
  720                       $m_var_list_update["cat"] = $cat;
  721                       $var_list_update["t"] = $element->attributes["_template"];
  722                       if(strlen($element->attributes["_template"]))
  723                       {
  724                         $ret = "<A CLASS=\"topic_edit\" HREF=\"".HREF_Wrapper()."\">";
  725                         $text = $element->attributes["_text"];
  726                         if(!strlen($text))
  727                         {
  728                           $text = $element->attributes["_plaintext"];
  729                           if(!strlen($text))
  730                           {
  731                               if(strlen($element->attributes["_image"]))
  732                               {
  733                                   $text = "<IMG SRC=\"".$element->attributes["_image"]."\" BORDER=\"0\" alt=\"\">";
  734                               }
  735                           }
  736                           $ret .= $text."</A>";
  737                         }
  738                         else
  739                           $ret .= language($text)."</A>";
  740                       }
  741                       else
  742                           $ret = "[no template]";
  743                   }
  744                   else
  745                       $ret = "";
  746                   unset($bb_var_list_update["top"], $var_list_update["t"],$m_var_list_update["cat"]);
  747               break;
  748  
  749               case "link_reply":
  750                   /*
  751                   @field:topic.link_reply
  752                   @description: Rturns a link to post a reply to the topic. A complete anchor tag is returned, and the tag class is set to 'topic_reply'
  753                   @attrib:_template:tpl:Template link should point to
  754                   @attrib:_text:lang:Language tag to display as the link text
  755                   @attrib:_plaintext:: Plain text to use instead of language tag
  756                   @attrib:image::Image URL to display in the anchor tag
  757                   */
  758                   if(($objSession->HasCatPermission("TOPIC.REPLY.ADD") ||
  759                      $objSession->Get("PortalUserId")==$this->Get("OwnerId"))
  760                      && $this->Get("TopicType")==1)
  761                   {
  762                       $bb_var_list_update["top"] = $this->Get("TopicId");
  763                       $var_list_update["t"] = $element->attributes["_template"];
  764                       if(strlen($element->attributes["_template"]))
  765                       {
  766                         $ret = "<A CLASS=\"topic_reply\" HREF=\"".HREF_Wrapper()."\">";
  767                         $text = $element->attributes["_text"];
  768                         if(!strlen($text))
  769                         {
  770                           $text = $element->attributes["_plaintext"];
  771                           if(!strlen($text))
  772                           {
  773                               if(strlen($element->attributes["_image"]))
  774                               {
  775                                   $text = "<IMG SRC=\"".$element->attributes["_image"]."\" BORDER=\"0\" alt=\"\">";
  776                               }
  777                           }
  778                           $ret .= $text."</A>";
  779                         }
  780                         else
  781                           $ret .= language($text)."</A>";
  782                       }
  783                       else
  784                           $ret = "";
  785                   }
  786                   else
  787                       $ret = "";
  788                   unset($bb_var_list_update["top"],$var_list_update["t"]);
  789               break;
  790  
  791               case "add_favorite_link":
  792                   /*
  793                   @field:topic.add_favorite_link
  794                   @description:Returns a URL to add this topic to the user's favorites
  795                                   @attrib:_template:tpl:Template URL should point to
  796                                   */
  797                   $t = $element->attributes["_template"];
  798                   if(!strlen($t))
  799                       $t = $var_list["t"];
  800                   $ret = $this->ItemURL($t,FALSE,"bb_add_favorite");
  801               break;
  802               case "del_favorite_link":
  803                   /*
  804                   @field:topic.del_favorite_link
  805                   @description:Returns a URL to remove this link from the user's favorites
  806                                   @attrib:_template:tpl:Template URL should point to
  807                                   */
  808                   $t = $element->attributes["_template"];
  809                   if(!strlen($t))
  810                       $t = $var_list["t"];
  811                   $ret = $this->ItemURL($t,FALSE,"bb_del_favorite");
  812               break;
  813                           /*
  814                                   @field:topic.favorite_toggle
  815                                   @description: Returns a link to set or reset the favorite flag for the current user
  816                                   @attrib: _template:tpl:Template to link to if user has the FAVORITES permission (defaults to current template)
  817                                   @attrib: _denytemplate:tpl: Template to link to if user does not have favorites permission (ie Guest)  Defaults to current template
  818                                   @attrib: _addlabel:lang:Language tag to display if link is to add favorite
  819                                   @attrib: _addimage::Image url to include in link if adding favorite
  820                                   @attrib: _dellabel:lang:Language tag to display if item is already a favorite
  821                                   @attrib: _delimage::Image url to include in link if removing the favorite
  822                           */
  823               case "favorite_toggle":
  824  
  825                   $t = $element->attributes["_template"];
  826                   if(!strlen($t))
  827                           $t = $var_list["t"];
  828  
  829                   if(!$this->IsFavorite())
  830                   {
  831                           $action = "bb_add_favorite";
  832                           if (!strlen($element->attributes["_addlabel"])) {
  833                                   $text = "<IMG SRC=\"".$element->attributes["_addimage"]."\" BORDER=\"0\" alt=\"\">";
  834                           }
  835                           else {
  836                                   $label = $element->attributes["_addlabel"];
  837                           }
  838                   }
  839                   else
  840                   {
  841                           $action = "bb_del_favorite";
  842                           if (!strlen($element->attributes["_dellabel"])) {
  843                                   $text = "<IMG SRC=\"".$element->attributes["_delimage"]."\" BORDER=\"0\" alt=\"\">";
  844                           }
  845                           else {
  846                           $label = $element->attributes["_dellabel"];
  847                     }
  848                   }
  849                   if (strlen($label)) {
  850                           $text = language($label);
  851                   }
  852                   $ret = "<A ".$extra_attribs." HREF=\"".$this->ItemURL($t,FALSE,$action)."\">".$text."</A>";
  853               break;
  854               case "admin_icon":
  855                   if( $element->GetAttributeByName('_fulltag') )
  856                   {
  857                       $ret = "<IMG $extra_attribs SRC=\"".$this->StatusIcon()."\" alt=\"\">";
  858                   }
  859                   else
  860                       $ret = $this->StatusIcon();
  861               break;
  862               case "admin_modified":
  863                   if($this->Get("Modified")<=0)
  864                                           return "-";
  865                                   return LangDate($this->Get("Modified"))."<br>".LangTime($this->Get("Modified"));
  866                   break;
  867               case "post_pagelist":
  868                   /*
  869                   @field:topic.post_pagelist
  870                   @description: Returns a page navigation link set for this topic, assuming the current page of the post list is page 1.  If less that one page full of posts exists, nothing is returned
  871                   @attrib:_DestTemplate:tpl: Template the links should point to
  872                   @attrib:_PagesToList:int: Number of pages listed in the bar
  873                   */
  874                   $plist = new clsPostingList();
  875                   $plist->TopicID = $this->Get('TopicId'); //$this->TopicID;
  876                   $where = 'TopicId = '.$this->Get('TopicId');
  877                   $plist->QueryItemCount = $this->GetPosts();
  878                   $plist->Page = 0;
  879                   $t = $element->attributes['_desttemplate'];
  880                   $PagesToList = $element->attributes['_pagestolist'];
  881                   if (!is_numeric($PagesToList)) $PagesToList = 10;
  882                   if ($plist->QueryItemCount > $objConfig->Get('Perpage_Postings'))
  883                   {
  884                                           $ret = $plist->GetPageLinkList($t,'',$PagesToList, $extra_attribs);
  885                   }
  886                   else
  887                   {
  888                       $ret = '';
  889                   }
  890               break;
  891               case "postedby":
  892                   /*
  893                   @field:topic.postedby
  894                   @description:Returns the login name of the last poster in this topic
  895                   */
  896                   $ret = $this->Get("PostedBy");
  897  
  898                   if ($ret == '') {
  899                           $ret = admin_language("lu_Guest");
  900                   }
  901               break;
  902                   case "admin_cell_back":
  903                 $ret = int_table_color_ret();
  904               break;
  905                   /*
  906                     @field:topic.rating
  907                     @description:Displays the topic rating
  908                                     @attrib:_displaymode:: How the rating should be displayed<br>
  909                                           <UL>
  910                                             <LI>"Numerical": Show the decimal value
  911                                             <LI>"Text": Show the text version
  912                                             <LI>"Graphical":Show images representing the rating
  913                                           </UL>
  914                                     @attrib:_onimage::on image tick shown in graphical display mode
  915                                     @attrib:_offimage::off image tick shown in graphical display mode
  916                                     @attrib:_separator::In graphical display mode, this html is placed between each tick image
  917                                   */
  918                   /*
  919                   @field:topic.reviews
  920                   @description:Return the number of reviews for think link
  921                                   @attrib:_today:bool:Count reviews added today only
  922                                   */
  923               case "votes":
  924                   /*
  925                   @field:topic.votes
  926                   @description:Return the number of rating votes for this topic
  927                                   */
  928                   $ret = $this->Get("CachedVotesQty");
  929                   break;
  930                   
  931                   
  932               case 'icon':
  933                   $icons = Array();
  934                   $icons['new'] = $element->GetAttributeByName('_new_icon');
  935                   $icons['no_new'] = $element->GetAttributeByName('_no_new_icon');
  936                   $icons['locked'] = $element->GetAttributeByName('_locked_icon');
  937  
  938                                   
  939                   if ($this->Get('TopicType') == 0 || $objSession->Get('PortalUserId') <= 0) {
  940                           $ret = $icons['locked'];
  941                           break;
  942                   }
  943  
  944                   $topic_modified = $this->Get('Modified');
  945                   if (!$topic_modified) {
  946                           $topic_modified = $this->Get('CreatedOn');
  947                   }
  948  
  949                   $last_login = $objSession->GetPersistantVariable('LastLogin');
  950  
  951                   if ($last_login < $topic_modified) {
  952                           $ret = $icons['new'];
  953                   }
  954                   else {
  955                           $ret = $icons['no_new'];
  956                   }
  957                   break;
  958  
  959                   /*
  960                                   @field:topic.new
  961                                   @description:returns text if topic's status is "new"
  962                                   @attrib:_label:lang: Text to return if status is new
  963                                   */
  964                   /*
  965                                   @field:topic.pop
  966                                   @description:returns text if topic's status is "popular"
  967                                   @attrib:_label:lang: Text to return if status is popular
  968                                   */
  969                   /*
  970                                   @field:topic.hot
  971                                   @description:returns text if topic's status is "hot"
  972                                   @attrib:_label:lang: Text to return if status is "hot"
  973                                   */
  974                   /*
  975                                   @field:topic.pick
  976                                   @description:returns text if topic's status is "hot"
  977                                   @attrib:_label:lang: Text to return if status is "hot"
  978                                   */
  979               }
  980               if(!isset($ret))
  981                 $ret = parent::ParseObject($element);
  982           }
  983           else
  984           {
  985               $ret = $this->parsetag($element->name);
  986           }
  987           return $ret;
  988       }
  989  
  990       function parsetag($tagname)
  991       {
  992        global $objConfig, $objSession, $objUsers, $var_list_update, $bb_var_list_update, $bb_var_list;
  993  
  994        switch($tagname)
  995            {
  996                   case "topic_admin_icon":
  997                           return $this->StatusIcon();
  998                   break;
  999                   case "topic_id":
  1000                           return $this->Get("TopicId");
  1001                           break;
  1002           case "topic_resourceid":
  1003             return $this->Get("ResourceId");
  1004             break;
  1005                   case "topic_modified":
  1006                           if ($this->Get('Modified') <= 0) {
  1007                                   return '';
  1008                           }
  1009                           return LangDate($this->Get('Modified'), 0, true);
  1010                           break;
  1011                           
  1012           case "topic_modified_time":
  1013               if ($this->Get('Modified') <= 0) {
  1014                  return '';
  1015               }
  1016               return LangTime($this->Get('Modified'), 0, true);
  1017           break;
  1018  
  1019           case "topic_admin_modified":
  1020               if($this->Get("Modified")<=0)
  1021                                   return "-";
  1022                           return LangDate($this->Get("Modified"))."<br>".LangTime($this->Get("Modified"));
  1023           break;
  1024           case "topic_created":
  1025               if ($this->Get('CreatedOn') <= 0) {
  1026                   return '';
  1027               }
  1028               return LangDate($this->Get('CreatedOn'), 0, true);
  1029                   break;
  1030                   
  1031           case "topic_created_time":
  1032               if ($this->Get('CreatedOn') <= 0) {
  1033                   return '';
  1034               }
  1035               return LangTime($this->Get('CreatedOn'), 0, true);
  1036           break;
  1037  
  1038                   case "topic_text":
  1039                           return inp_unescape($this->Get("TopicText"));
  1040                           break;
  1041                   case "topic_delete":
  1042                           if($this->CheckPermission("DELETE"))
  1043                           {
  1044                                   $bb_var_list_update["top"] = $this->Get("TopicId");
  1045                                   return "<A CLASS=\"topic_delete\" HREF=\"".HREF_Wrapper('', Array('Action' => 'bb_topic_delete') ) ."\">".language("delete")."</A>";
  1046                           }
  1047                           else
  1048                                   return "";
  1049                           break;
  1050                   case "topic_name":
  1051                           return inp_unescape($this->Get("TopicText"));
  1052                           break;
  1053                   case "topic_views":
  1054                           return $this->Get("Views");
  1055                           break;
  1056                   case "topic_posts":
  1057                           return $this->GetPosts();
  1058                           break;
  1059                   case "topic_replies":
  1060                           return $this->GetPosts() - 1;
  1061                           break;
  1062           case "topic_priority":
  1063               if($this->Get("Priority")>0)
  1064               {
  1065                   return (int)$this->Get("Priority");
  1066               }
  1067               else
  1068                   return "";
  1069               break;
  1070                   case "topic_pick":
  1071                           if ($this->Is("EditorsPick"))
  1072                                   return "pick";
  1073                           break;
  1074                   case "topic_new":
  1075                           if ($this->IsNewItem())
  1076                                   return "new";
  1077                           break;
  1078                   case "topic_pop":
  1079                           if ($this->IsPopItem())
  1080                                   return "pop";
  1081                           break;
  1082           case "topic_hot":
  1083               if ($this->IsHotItem())
  1084                   return "hot";
  1085               break;
  1086           case "topic_poster":
  1087               return $this->Get("PostedBy");
  1088               break;
  1089                   case "topic_category":
  1090                           return $this->Get("CategoryId");
  1091                           break;
  1092                   case "topic_last_post":
  1093                           return LangDate($this->Get("Modified"));
  1094                           break;
  1095                   case "topic_link":
  1096                           $var_list_update["t"] = "inbulletin/bb_post_list";
  1097                           $bb_var_list_update["top"] = $this->Get("TopicId");
  1098                           $bb_var_list_update["cat"] = $this->Get("CategoryId");
  1099               $bb_var_list_update["pp"]=1;
  1100                           $ret = HREF_Wrapper();
  1101                           unset($var_list_update["t"], $bb_var_list_update["top"]);
  1102  
  1103                           return $ret;
  1104                           break;
  1105           case "topic_review_link":
  1106               $var_list_update["t"] = "inbulletin/bb_reviews";
  1107               $bb_var_list_update["top"] = $this->Get("TopicId");
  1108               $bb_var_list_update["cat"] = $this->Get("CategoryId");
  1109               $bb_var_list_update["pp"]=1;
  1110               $ret = HREF_Wrapper();
  1111               unset($var_list_update["t"], $bb_var_list_update["top"]);
  1112  
  1113               return $ret;
  1114               break;
  1115  
  1116           case "topic_rate_link":
  1117               $var_list_update["t"] = "inbulletin/bb_rate";
  1118               $bb_var_list_update["top"] = $this->Get("TopicId");
  1119               $bb_var_list_update["cat"] = $this->Get("CategoryId");
  1120               $bb_var_list_update["pp"]=1;
  1121               $ret = HREF_Wrapper();
  1122               unset($var_list_update["t"], $bb_var_list_update["top"]);
  1123  
  1124               return $ret;
  1125               break;
  1126           case "topic_num_reviews":
  1127               $ret = $this->ReviewCount();
  1128               return $ret;
  1129               break;
  1130           case "topic_votes":
  1131               return $this->Get("CachedVotesQty");
  1132               break;
  1133           case "topic_rating":
  1134               return round($this->Get("CachedRating"),1);
  1135               break;
  1136                   case "topic_rating_txt":
  1137                           return RatingText($this->Get("CachedRating"));
  1138                           break;
  1139                   case "topic_type_img":
  1140                           $last_login = $objSession->GetPersistantVariable("LastLogin");
  1141  
  1142                           if ($objSession->Get("PortalUserId") == -2)
  1143                           {
  1144                                   $n = $this->GetPosts();
  1145                                   if ($n > 25)
  1146                                           return "inbulletin/images/hot_folder.gif";
  1147                                   else
  1148                                           return "inbulletin/images/folder.gif";
  1149  
  1150                           }
  1151  
  1152                           $n = $this->GetPostsSince($last_login);
  1153                           if ($n > 25)
  1154                                   return "inbulletin/images/hot_red_folder.gif";
  1155                           elseif ($n > 0)
  1156                                   return "inbulletin/images/red_folder.gif";
  1157                           else
  1158                           {
  1159                           $n2 = $this->GetPosts();
  1160                           if ($n2 > 25)
  1161                                   return "inbulletin/images/hot_folder.gif";
  1162                           else
  1163                                   return "inbulletin/images/folder.gif";
  1164                           }
  1165                           break;
  1166  
  1167           case "topic_admin_cell_back":
  1168              return int_table_color_ret();
  1169                   default:
  1170               return "Undefined:$tagname";
  1171                           break;
  1172         }
  1173       }
  1174  
  1175      function UpdateCategoryPostCount($CatId=NULL)
  1176      {
  1177            global $objCatList,$objCountCache;
  1178  
  1179            if(!is_numeric($CatId))
  1180              $CatId = $objCatList->CurrentCategoryID();
  1181  
  1182            $PostCount = 0;
  1183            $sql = "SELECT SUM(Posts) as PostCount,count(TopicId) as TopicCount FROM ".$this->tablename." INNER JOIN ".GetTablePrefix()."CategoryItems ON ";
  1184            $sql .= "(".$this->tablename.".ResourceId=".GetTablePrefix()."CategoryItems.ItemResourceId) WHERE CategoryId=$CatId AND Status=1";
  1185            $rs = $this->adodbConnection->Execute($sql);
  1186            if($rs && !$rs->EOF)
  1187              $PostCount = $rs->fields["PostCount"];
  1188  
  1189            if($PostCount>0)
  1190              $PostCount = $PostCount - (int)$rs->fields["TopicCount"];
  1191            $sql = "UPDATE ".$objCountCache->SourceTable." SET Value=".(int)$PostCount.",LastUpdate=".adodb_date("U")." WHERE ItemType=30 AND ListType=30 AND ExtraId=$CatId";
  1192            $this->adodbConnection->Execute($sql);
  1193      }
  1194  
  1195      function &AddPost($PosterAlias,$Pending, $PostingText, $Subject="")
  1196      {
  1197         global $objUsers,$objSession, $objCatList;
  1198  
  1199         $u =& $objSession->CurrentUser;
  1200  
  1201         if (is_object($u)) {
  1202           $posts = (int)$u->GetPersistantVariable("bb_posts");
  1203           $posts++;
  1204           $u->SetPersistantVariable("bb_posts",$posts);
  1205         }
  1206  
  1207         $p = New clsPosting(NULL);
  1208             $p->Set(array("PosterAlias", "Pending", "PostingText", "TopicId"),
  1209                 array($PosterAlias, $Pending, str_replace("env=".$objSession->GetSessionKey(), "env=",$PostingText), $this->Get("TopicId")));
  1210         $p->Set("IPAddress",$_SERVER["REMOTE_ADDR"]);
  1211         $p->Set("CreatedOn",adodb_date("U"));
  1212         if (is_object($u)) {
  1213           $p->Set("CreatedById",$u->Get("PortalUserId"));
  1214         }
  1215         if(strlen($Subject))
  1216         {
  1217             $p->Set("Subject",$Subject);
  1218         }
  1219         $p->Create();
  1220  
  1221  
  1222         $this->Increment("Posts");
  1223         $this->Set(array("Modified", "ModifiedById"), array(adodb_mktime(), $objSession->Get("PortalUserId")));
  1224         $this->Set("LastPostId",$p->Get("PostingId"));
  1225         $this->Set("LastPostDate",$p->Get("CreatedOn"));
  1226         $this->Update();
  1227  
  1228         $this->UpdateCategoryPostCount();
  1229         if($this->Get("NotifyOwnerOnChanges"))
  1230         {
  1231             $this->SendUserEventMail("POST.ADD",$this->Get("OwnerId"));
  1232         }
  1233  
  1234         if (is_object($u)) {
  1235                 $this->SendUserEventMail("POST.ADD",$u->Get("PortalUserId"));
  1236         }
  1237         $this->SendAdminEventMail("POST.ADD");
  1238  
  1239         $CategoryId = $this->Get("CategoryId");
  1240         if(!is_numeric($CategoryId))
  1241            $CategoryId = $objCatList->CurrentCategoryID();
  1242  
  1243         return $p;
  1244      }
  1245  
  1246      function GetLastPostId()
  1247      {
  1248  
  1249          $sql = "SELECT PostingId FROM ".GetTablePrefix()."Posting WHERE TopicId=".$this->Get("TopicId");
  1250          $sql .= " ORDER BY CreatedOn DESC LIMIT 1";
  1251          $rs = $this->adodbConnection->Execute($sql);
  1252          if($rs && !$rs->EOF)
  1253          {
  1254              $ret = $rs->fields["PostingId"];
  1255          }
  1256          else
  1257              $ret = 0;
  1258          return $ret;
  1259      }
  1260  
  1261      function CopyToNewResource($TargetCat = NULL,$NameField="")
  1262      {
  1263        $OldTopicId = $this->Get("TopicId");
  1264  
  1265        parent::CopyToNewResource($TargetCat,$NameField);
  1266        $p = new clsPostingList();
  1267        $p->TopicID = $OldTopicId;
  1268        $sql = "SELECT * FROM ".$p->SourceTable." WHERE TopicId=$OldTopicId ";
  1269        $p->Query_Item($sql,-1,-1);
  1270        if($p->NumItems()>0)
  1271        {
  1272          foreach($p->Items as $post)
  1273          {
  1274             $post->Set("TopicId",$this->Get("TopicId"));
  1275             $post->UnsetIdField();
  1276                     $post->Create();
  1277          }
  1278          $this->Set("Posts",$p->NumItems());
  1279        }
  1280      }
  1281  
  1282      function SetTodayPosts($IncrementBy)
  1283      {
  1284                   $DateNow = adodb_date('Y-m-d', adodb_mktime() );
  1285                   $LastTodayDate = $this->Get('TodayDate');
  1286                   $TodayPosts = ($DateNow == $LastTodayDate) ? $this->Get('TodayPosts') : 0;
  1287                   $TodayPosts += $IncrementBy;
  1288                   $this->Set('TodayDate', $DateNow);
  1289                   $this->Set('TodayPosts', $TodayPosts);
  1290                   $this->Update();
  1291      }
  1292  
  1293   }
  1294  
  1295   class _clsTopicList extends clsCatItemList {
  1296      //var $Page;
  1297      var $CategoryID;
  1298      var $Permissions;
  1299     // var $PerPageVar;
  1300  
  1301           function _clsTopicList($CatID=NULL)
  1302           {
  1303             global $objSession,$bb_var_list;
  1304  
  1305             $this->clsCatItemList();
  1306            
  1307             $this->Prefix = 'bb';
  1308             $this->classname="clsTopic";
  1309             $this->SourceTable = GetTablePrefix()."Topic";
  1310             $this->Page = $bb_var_list["tp"];
  1311             $this->BasePermission="TOPIC";
  1312             $this->PerPageVar = "Perpage_Topics";
  1313             $this->PageEnvar="bb_var_list_update";
  1314             $this->PageEnvarIndex = "tp";
  1315  
  1316                     $this->PerPageVarLong = "Perpage_Topics";
  1317             $this->PerPageShortVar = "Perpage_Topics_Short";
  1318  
  1319             $this->AddSortField('Topic_SortField','Topic_SortOrder');
  1320             $this->AddSortField('Topic_SortField2','Topic_SortOrder2');
  1321  
  1322             $this->ItemType = TYPE_TOPIC;
  1323  
  1324             if( isset($CatID) ) $this->CategoryID = $CatID;
  1325             $this->AdminSearchFields = array('TopicText','PostedBy');
  1326           }
  1327  
  1328           function SaveNewPage()
  1329           {
  1330                   global $bb_var_list;
  1331                   $bb_var_list["tp"] = $this->Page;
  1332           }
  1333  
  1334           function GetHotValue()
  1335           {
  1336                   global $objConfig;
  1337  
  1338                   $ado = &GetADODBConnection();
  1339                   $sql = "SELECT Views FROM ".GetTablePrefix()."Topic ORDER BY Views DESC LIMIT 0,".$objConfig->Get("Topic_MaxHotNumber");
  1340                   $rs = $ado->Execute($sql);
  1341  
  1342                   $hot_val = 0;
  1343                   while ($rs && !$rs->EOF) {
  1344                           if ($rs->fields['Views'] > 0) {
  1345                                   $hot_val = $rs->fields['Views'];
  1346                           }
  1347                           $rs->MoveNext();
  1348                   }
  1349  
  1350                   return $hot_val;
  1351           }
  1352  
  1353           function GetPopValue()
  1354           {
  1355           global $PopValues,$objConfig, $objSystemCache;
  1356  
  1357           if( isset($PopValues['topic']) && is_numeric($PopValues['topic']) )
  1358           {
  1359                   return $PopValues['topic'];
  1360           }
  1361           else
  1362           {
  1363                   $PopValues['topic'] = $objConfig->Get('Topic_MinPopRating');
  1364                   /*$CachedValue = $objSystemCache->GetValue("TopicPopValue","inbulletin","");
  1365                   if(strlen($CachedValue))
  1366                   {
  1367                   $PopValues["topic"] = $CachedValue;
  1368                   return $CachedValue;
  1369                   }
  1370                   $ado = &GetADODBConnection();
  1371                   $sql = "SELECT CachedRating FROM ".GetTablePrefix()."Topic  WHERE CachedVotesQty > ".(int)$objConfig->Get("Topic_MinPopVotes")." ORDER BY CachedRating DESC,CachedVotesQty DESC LIMIT 0,".(int)$objConfig->Get("Topic_MinPopRating");
  1372  
  1373                   $rs = $ado->Execute($sql);
  1374                   $PopValues["topic"] = 0;
  1375                   while($rs && !$rs->EOF)
  1376                   {
  1377                   $PopValues["topic"] = $rs->fields["Views"];
  1378                   $rs->MoveNext();
  1379                   }*/
  1380                   $objSystemCache->EditCacheItem('TopicPopValue',$PopValues['topic'],'inbulletin',adodb_mktime()+3600,'');
  1381                   return $PopValues['topic'];
  1382           }
  1383           }
  1384  
  1385  
  1386       function HasPermission($PermissionName)
  1387       {
  1388           global $objSession,$objCatList;
  1389  
  1390           if($this->CategoryID==0)
  1391           {
  1392               $this->CategoryID=$objCatList->CurrentCategoryID();
  1393           }
  1394           $cat =& $objCatList->GetCategory($this->CategoryID);
  1395           if(is_object($cat))
  1396           {
  1397             return ($cat->HasPermission($PermissionName,$objSession->Get("GroupId")));
  1398           }
  1399           else
  1400               return FALSE;
  1401       }
  1402  
  1403       function &Add_Topic($TopicText, $CategoryId, $Status, $Pick, $OwnerNotify,$CreatedOn, $UserID = null, $add_fields = null, $auto_filename = 1, $filename = '')
  1404       {
  1405           // $add_fields - additional fields
  1406           global $objSession,$objUsers;
  1407  
  1408           $t = new clsTopic(NULL);
  1409   //        $filename = $t->StripDisallowed($filename);
  1410  
  1411           $t->tablename = $this->SourceTable;
  1412           $u = $objUsers->GetItem( isset($UserID) ? $UserID : $objSession->Get("PortalUserId") );
  1413               $t->Set(array("TopicText", "OwnerId", "TopicType","Status","PostedBy","EditorsPick",
  1414                         "NotifyOwnerOnChanges","CreatedOn", 'AutomaticFilename'),
  1415                   array(str_replace("env=".$objSession->GetSessionKey(), "env=",$TopicText), $u->Get("PortalUserId"), 1,$Status,$u->Get("Login"),$Pick,
  1416                         $OwnerNotify, $CreatedOn, $auto_filename));
  1417  
  1418           if( isset($add_fields) )
  1419                   foreach($add_fields     as $field => $value)
  1420                           $t->Set($field, $value);
  1421  
  1422               $t->Create();
  1423           $t->AddToCategory($CategoryId);
  1424           $t->SendUserEventMail("TOPIC.ADD",$u->Get("PortalUserId"));
  1425           $t->SendAdminEventMail("TOPIC.ADD");
  1426           return $t;
  1427       }
  1428  
  1429       function LockTopic($TopicId)
  1430       {
  1431           $p = $this->GetItem($TopicId);
  1432           $p->Set("TopicType", 0);
  1433           $p->Update();
  1434  
  1435           return $p;
  1436       }
  1437  
  1438       function &Edit_Topic($TopicId,$TopicSubject,$User,$Status,$Pick, $New,$Hot,$Pop,
  1439                           $OwnerNotify,$CreatedOn,$ModifiedOn, $Rating, $Votes, $Views, $Priority=0,$PostedBy="",
  1440                           $IsLocked = 0, $auto_filename = 1, $filename = '')
  1441       {
  1442           global $objUsers, $objSession;
  1443           $p = $this->GetItem($TopicId);
  1444   //        $filename = $p->StripDisallowed($filename);
  1445  
  1446           if(!strlen($PostedBy))
  1447           {
  1448                   $PostedByUser = $objUsers->GetUser($User);
  1449                   if(is_object($PostedByUser))
  1450                   {
  1451                           $PostedBy = $PostedByUser->Get("Login");
  1452                   }
  1453                   else
  1454                   {
  1455                           if($User==-1)
  1456                           {
  1457                                   $PostedBy="Admin";
  1458                           }
  1459                           else
  1460                             $PostedBy="";
  1461                   }
  1462           }
  1463           if ($IsLocked == 1) {
  1464                   $TopicType = 0;
  1465           }
  1466           else {
  1467                   $TopicType = 1;
  1468           }
  1469  
  1470           $p->Set(array("TopicText","ModifiedById","Status", "EditorsPick","NewItem","HotItem","PopItem",
  1471                         "NotifyOwnerOnChanges","CreatedOn","Modified", "CachedRating","CachedVotesQty",
  1472                         "Views","Priority","PostedBy", "TopicType", 'AutomaticFilename'),
  1473                   array(str_replace("env=".$objSession->GetSessionKey(), "env=", $TopicSubject),$User,$Status,$Pick,$New,$Hot,$Pop,
  1474                         $OwnerNotify,$CreatedOn,$ModifiedOn,$Rating,$Votes,$Views, $Priority,$PostedBy, $TopicType, $auto_filename));
  1475           $p->Update();
  1476           if($p->Get("NotifyOwnerOnChanges"))
  1477           {
  1478               $p->SendUserEventMail("TOPIC.MODIFY",$p->Get("OwnerId"));
  1479           }
  1480           $p->SendAdminEventMail("TOPIC.MODIFY");
  1481           return $p;
  1482       }
  1483  
  1484  
  1485       function PasteFromClipboard($TargetCat)
  1486       {
  1487         global $objSession,$objCatList, $objPostingList;
  1488  
  1489         $clip = $objSession->GetVariable("ClipBoard");
  1490         if(strlen($clip))
  1491         {
  1492             $ClipBoard = ParseClipboard($clip);
  1493             $IsCopy = (substr($ClipBoard["command"],0,4)=="COPY") || ($ClipBoard["source"] == $TargetCat);
  1494  
  1495             $item_ids = explode(",",$ClipBoard["ids"]);
  1496             for($i=0;$i<count($item_ids);$i++)
  1497             {
  1498                 $item = $this->GetItem($item_ids[$i]);
  1499                 if(!$IsCopy)
  1500                 {
  1501                     $item->MoveToCategory($ClipBoard["source"],$TargetCat);
  1502                     $clip = str_replace("CUT","COPY",$clip);
  1503                     $objSession->SetVariable("ClipBoard",$clip);
  1504                 }
  1505                 else
  1506                 {
  1507                   if($ClipBoard["source"]==$TargetCat)
  1508                   {
  1509                       $item->CopyToNewResource($TargetCat,"TopicText");
  1510                       $item->AddToCategory($TargetCat);
  1511  
  1512                   }
  1513                   else
  1514                   {
  1515                     $CatCount = $item->CategoryMemberCount();
  1516                     if($CatCount==0)
  1517                     {
  1518                       $item->AddToCategory($TargetCat);
  1519                     }
  1520                     else
  1521                     {
  1522                       $item->CopyToNewResource($TargetCat,"TopicText");
  1523                       $item->AddToCategory($TargetCat);
  1524                     }
  1525                   }
  1526                 }
  1527             }
  1528         }
  1529       }
  1530  
  1531       function CountPending()
  1532       {
  1533           return TableCount($this->SourceTable,"Status=".STATUS_PENDING,0);
  1534       }
  1535  
  1536       function LoadTopics($where="",$orderBy = "", $JoinCats=TRUE,$SkipClear=FALSE,$fix_method = 'set_first')
  1537       {
  1538           global $objConfig;
  1539  
  1540           if(!$SkipClear)
  1541               $this->Clear();
  1542  
  1543           $limit = $this->GetPageLimitSQL();
  1544  
  1545                   $this->QueryItemCount=TableCount($this->SourceTable,$where,$JoinCats);
  1546  
  1547          return $this->Query_Topic($where,$orderBy,$limit, $JoinCats, $fix_method);
  1548       }
  1549  
  1550       function Query_Topic($whereClause,$orderByClause=NULL,$limit=NULL, $JoinCats=TRUE, $fix_method = 'set_first')
  1551       {
  1552             global $objSession, $Errors;
  1553  
  1554         if($JoinCats)
  1555         {
  1556           $sql = "SELECT * FROM ".$this->SourceTable." INNER JOIN ".GetTablePrefix()."CategoryItems ON ".GetTablePrefix()."CategoryItems.ItemResourceId=".
  1557                  $this->SourceTable.".ResourceId";
  1558         }
  1559         else
  1560         {
  1561             $sql = "SELECT * FROM ".$this->SourceTable;
  1562         }
  1563  
  1564         if(isset($whereClause))
  1565             $sql = sprintf('%s WHERE %s',$sql,$whereClause);
  1566         if(isset($orderByClause) && strlen(trim($orderByClause))>0)
  1567         {
  1568           $sql .= " ".$orderByClause;
  1569         }
  1570  
  1571         if($objSession->HasSystemPermission("DEBUG.LIST"))
  1572             echo htmlentities($sql,ENT_NOQUOTES)."<br>\n";
  1573  
  1574         return $this->Query_Item($sql,null, $fix_method);
  1575       }
  1576  
  1577       function &GetCurrentTopic()
  1578       {
  1579           global $bb_var_list;
  1580  
  1581           $t =& $this->GetItem($bb_var_list["top"]);
  1582           return $t;
  1583       }
  1584  
  1585       function CurrentTopicID()
  1586       {
  1587           global $bb_var_list;
  1588  
  1589           return $bb_var_list["top"];
  1590       }
  1591  
  1592       function LoadTopicsCategory($attribs)
  1593       {
  1594           global $objCatList, $objSession, $objConfig, $objPermissions;
  1595  
  1596           $OrderBy ='';
  1597           $CatId = $attribs['_catid'];
  1598           if(!is_numeric($CatId))
  1599           $CatId = $objCatList->CurrentCategoryID();
  1600  
  1601           if(!$CatId && (int)$attribs['_useroot'])
  1602           $CatId = (int)$objConfig->Get('Topic_Root');
  1603  
  1604           $this->CategoryID=$CatId;
  1605           $this->Clear();
  1606  
  1607           $limit = $this->GetPageLimitSQL();
  1608  
  1609           if($objSession->HasCatPermission('TOPIC.VIEW',$CatId))
  1610           {
  1611                   $sort_field = trim( $objSession->GetPersistantVariable('Topic_SortField') );
  1612                   if( !strlen($sort_field) ) $sort_field = trim($objConfig->Get('Topic_SortField'));
  1613  
  1614                   if($sort_field)
  1615                   {
  1616                           $OrderBy = 'Priority DESC, '.$sort_field.' '.
  1617                           $objSession->GetPersistantVariable('Topic_SortOrder');
  1618                   }
  1619                   else
  1620                   $OrderBy = 'Priority DESC';
  1621  
  1622                   $pre = GetTablePrefix();
  1623                   $s = $this->SourceTable;
  1624                   $sql = 'SELECT '.$s.'.*,lp.PosterAlias as LastPoster,lp.CreatedOn as PLastPostDate FROM '.$s.' INNER JOIN '.$pre.'CategoryItems ON ('.$pre.'CategoryItems.ItemResourceId='.$s.'.ResourceId) ';
  1625                   $sql .= ' LEFT JOIN '.$pre.'Posting as lp ON (lp.PostingId='.$s.'.LastPostId) WHERE ';
  1626  
  1627                   $where = 'CategoryId = '.$CatId.' AND '.$s.'.Status = 1 ';
  1628  
  1629                   $sql .= $where;
  1630                   $this->QueryItemCount=QueryCount($sql);
  1631  
  1632                   if (($sort_field != 'LastPoster') &&  ($sort_field != 'LastPostDate')) {
  1633                           $use_table = TRUE;
  1634                   }
  1635                   else {
  1636                           $use_table = FALSE;
  1637                   }
  1638                   //echo "$sort_field: $use_table<br>";
  1639                   $OrderBy = $this->QueryOrderByClause(TRUE, TRUE, $use_table);
  1640                   $sql .= " ".$OrderBy;
  1641                   //echo '<b>TopicList SQL</b>: '.$sql.'<br>';
  1642  
  1643                   return $this->Query_Item($sql);
  1644           }
  1645       }
  1646  
  1647       function CategoryCount($attribs=array())
  1648       {
  1649           global $objItemTypes;
  1650  
  1651           if(is_numeric($attribs["_itemtype"]))
  1652           {
  1653                   $item = $objItemTypes->GetItem($attribs["_itemtype"]);
  1654           }
  1655           else
  1656                   $item = $objItemTypes->GetTypeByName($attribs["_itemtype"]);
  1657  
  1658           if($item->Get("ItemType") != 30)
  1659           {
  1660                   return parent::CategoryCount($attribs);
  1661           }
  1662           else
  1663           {
  1664                   global $objPostingList;
  1665  
  1666                   return $objPostingList->CategoryCount($attribs);
  1667           }
  1668       }
  1669  
  1670       function SqlGlobalCount($attribs=array())
  1671       {
  1672                   global $objSession, $objItemTypes,$objPermissions, $objCatList;
  1673  
  1674                   //$old_cat=$objCatList->CurrentCategoryID()
  1675  
  1676           if(is_numeric($attribs['_itemtype']))
  1677           {
  1678                   $item = $objItemTypes->GetItem($attribs['_itemtype']);
  1679           }
  1680           else
  1681           {
  1682                   $item = $objItemTypes->GetTypeByName($attribs['_itemtype']);
  1683           }
  1684  
  1685           $t = $this->SourceTable;
  1686           $acl = $objSession->GetACLClause();
  1687           $cattable = GetTablePrefix().'CategoryItems';
  1688           $CategoryTable = GetTablePrefix().'Category';
  1689           $ptable = GetTablePrefix().'PermCache';
  1690           $VIEW = $objPermissions->GetPermId('TOPIC.VIEW');
  1691  
  1692           $where = '';
  1693           $today = adodb_mktime(0,0,0,adodb_date('m'),adodb_date('d'),adodb_date('Y'));
  1694  
  1695           if($item->Get('ItemType') == $this->ItemType)
  1696           {
  1697                           // count topics in current category & it's subcategories
  1698  
  1699                           if($attribs['_today'])
  1700                           {
  1701                                   $where = 'AND ('.$t.'.CreatedOn >= '.$today.')';
  1702                           }
  1703                           $sql = "SELECT count(*) as CacheVal FROM $t
  1704                                   INNER JOIN $cattable ON ($cattable.ItemResourceId=$t.ResourceId)
  1705                                   INNER JOIN $CategoryTable ON ($CategoryTable.CategoryId=$cattable.CategoryId)
  1706                                   INNER JOIN $ptable ON ($cattable.CategoryId=$ptable.CategoryId)
  1707                                   WHERE   ($acl AND PermId=$VIEW AND $cattable.PrimaryCat=1 AND $CategoryTable.Status=1) AND
  1708                                                   FIND_IN_SET(".$objCatList->CurrentCategoryID().", REPlACE(ParentPath,'|',',')) $where";
  1709                   return $sql;
  1710  
  1711           }
  1712           elseif($item->Get('ItemType') == 30)
  1713           {
  1714                   // counting post here
  1715                           if (getArrayValue($attribs, '_today'))
  1716                           {
  1717                                   $where = 'AND ('.$t.'. TodayDate = \''.adodb_date('Y-m-d', $today).'\')';
  1718                                   $CountField = 'TodayPosts';
  1719                           }
  1720                           else
  1721                           {
  1722                                   $CountField = 'Posts';
  1723                           }
  1724  
  1725                   $sql = "SELECT SUM($CountField) as CachedVal FROM $t ";
  1726                           $sql .="INNER JOIN $cattable ON ($cattable.ItemResourceId=$t.ResourceId) ";
  1727                   $sql .="INNER JOIN $CategoryTable ON ($CategoryTable.CategoryId=$cattable.CategoryId) ";
  1728                   $sql .="INNER JOIN $ptable ON ($cattable.CategoryId=$ptable.CategoryId) ";
  1729                   $sql .="WHERE ($acl AND PermId=$VIEW AND $cattable.PrimaryCat=1 AND $CategoryTable.Status=1) ";
  1730                   $sql .=" AND ($t.Status=1) AND FIND_IN_SET(".$objCatList->CurrentCategoryID().", REPlACE(ParentPath,'|',',')) $where";
  1731                   //echo "Posts count sql: $sql<br>";
  1732                   return $sql;
  1733           }
  1734       }
  1735  
  1736       function DoGlobalCount($attribs)
  1737       {
  1738           global $objItemTypes;
  1739  
  1740           if(is_numeric($attribs["_itemtype"]))
  1741           {
  1742                   $item = $objItemTypes->GetItem($attribs["_itemtype"]);
  1743           }
  1744           else
  1745                   $item = $objItemTypes->GetTypeByName($attribs["_itemtype"]);
  1746  
  1747           // ItemType: 30 - Posts, 3 - Topics
  1748  
  1749           if($item->Get("ItemType") != 30)
  1750           {
  1751                   return parent::DoGlobalCount($attribs);
  1752           }
  1753           else
  1754           {
  1755                   global $objPostingList;
  1756                   //echo "PostsCount: ".$objPostingList->DoGlobalCount($attribs)."<br>";
  1757                   return $objPostingList->DoGlobalCount($attribs);
  1758           }
  1759       }
  1760  
  1761       function CacheListExtraId($ListType)
  1762       {
  1763           if( !strlen($ListType) ) $ListType = '_';
  1764           switch($ListType)
  1765           {
  1766                   case '_':
  1767                           global $objCatList;
  1768                           return $objCatList->CurrentCategoryID();
  1769                           break;
  1770  
  1771                   default:
  1772                           return parent::CacheListExtraId($ListType);
  1773                           break;
  1774           }
  1775           return $ExtraId;
  1776       }
  1777  
  1778       function SqlMyItems($attribs=array())
  1779       {
  1780           global $objSession;
  1781  
  1782           if(getArrayValue($attribs,'_shortlist'))
  1783           {
  1784               $this->PerPageVar = $this->PerPageShortVar;
  1785           }
  1786           else
  1787             $this->PerPageVar = $this->PerPageVarLong;
  1788  
  1789                   $TableName = $this->SourceTable;
  1790                   $where" ".$TableName.".Status>0 AND ".$TableName.".OwnerId=".$objSession->Get("PortalUserId");
  1791           if(getArrayValue($attribs,'_today'))
  1792           {
  1793                           $today = adodb_mktime(0,0,0,adodb_date("m"),adodb_date("d"),adodb_date("Y"));
  1794                           $where .= " AND ($TableName.CreatedOn>=$today)";
  1795           }
  1796                   $CategoryTable = GetTablePrefix()."Category";
  1797                   $sql = "SELECT $TableName.*,$CategoryTable.CategoryId,$CategoryTable.CachedNavBar FROM $TableName ";
  1798               $p = $this->BasePermission.".VIEW";
  1799               $sql .= $this->GetJoinedSQL($p,null,$where); // maybe null will be CategoryId someday
  1800  
  1801               $OrderBy = $this->QueryOrderByClause(TRUE,TRUE,TRUE);
  1802           $sql .= " ".$OrderBy;
  1803  
  1804           return $sql;
  1805       }
  1806  
  1807       function ResetCache($CategoryId)
  1808       {
  1809           global $objCountCache;
  1810           $db =& GetADODBConnection();
  1811           $sql = 'SELECT ParentPath FROM '.GetTablePrefix().'Category WHERE CategoryId = '.$CategoryId;
  1812           $parents = $db->GetOne($sql);
  1813           $parents = substr($parents,1,strlen($parents)-2);
  1814           $parents = explode('|',$parents);
  1815           foreach($parents as $ParentCategoryId)
  1816           {
  1817                   $objCountCache->DeleteValue('_', TYPE_TOPIC, $ParentCategoryId, 0);     // total topic count
  1818                   $objCountCache->DeleteValue('_', TYPE_TOPIC, $ParentCategoryId, 1);     // total
  1819           }
  1820       }
  1821  
  1822   } /*clsTopicList*/
  1823  
  1824  
  1825   ?>