typo3/ext/tt_products/pi/class.tx_ttproducts.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 1999-2004 Kasper Skaarhoj (kasperYYYY@typo3.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00067 require_once(PATH_tslib."class.tslib_pibase.php");
00068 require_once(PATH_t3lib."class.t3lib_parsehtml.php");
00069 
00070 class tx_ttproducts extends tslib_pibase {
00071         var $cObj;              // The backReference to the mother cObj object set at call time
00072 
00073         var $searchFieldList="title,note,itemnumber";
00074 
00075                 // Internal
00076         var $pid_list="";
00077         var $uid_list="";                                       // List of existing uid's from the basket, set by initBasket()
00078         var $categories=array();                        // Is initialized with the categories of the shopping system
00079         var $pageArray=array();                         // Is initialized with an array of the pages in the pid-list
00080         var $orderRecord = array();                     // Will hold the order record if fetched.
00081 
00082 
00083                 // Internal: init():
00084         var $templateCode="";                           // In init(), set to the content of the templateFile. Used by default in getBasket()
00085 
00086                 // Internal: initBasket():
00087         var $basket=array();                            // initBasket() sets this array based on the registered items
00088         var $basketExtra;                                       // initBasket() uses this for additional information like the current payment/shipping methods
00089         var $recs = Array();                            // in initBasket this is set to the recs-array of fe_user.
00090         var $personInfo;                                        // Set by initBasket to the billing address
00091         var $deliveryInfo;                                      // Set by initBasket to the delivery address
00092 
00093                 // Internal: Arrays from getBasket() function
00094         var $calculatedBasket;                          // - The basked elements, how many (quantity, count) and the price and total
00095         var $calculatedSums_tax;                        // - Sums of goods, shipping, payment and total amount WITH TAX included
00096         var $calculatedSums_no_tax;                     // - Sums of goods, shipping, payment and total amount WITHOUT TAX
00097 
00098         var $config=array();
00099         var $conf=array();
00100         var $tt_product_single="";
00101         var $globalMarkerArray=array();
00102         var $externalCObject="";
00103 
00104 
00108         function main_products($content,$conf)  {
00109                 $GLOBALS["TSFE"]->set_no_cache();
00110 
00111                 // *************************************
00112                 // *** getting configuration values:
00113                 // *************************************
00114 
00115                         // getting configuration values:
00116                 $this->conf=$conf;
00117                 $this->config["code"] = strtolower(trim($this->cObj->stdWrap($this->conf["code"],$this->conf["code."])));
00118                 $this->config["limit"] = t3lib_div::intInRange($this->conf["limit"],0,1000);
00119                 $this->config["limit"] = $this->config["limit"] ? $this->config["limit"] : 50;
00120 
00121                 $this->config["pid_list"] = trim($this->cObj->stdWrap($this->conf["pid_list"],$this->conf["pid_list."]));
00122                 $this->config["pid_list"] = $this->config["pid_list"] ? $this->config["pid_list"] : $GLOBALS["TSFE"]->id;
00123 
00124                 $this->config["recursive"] = $this->cObj->stdWrap($this->conf["recursive"],$this->conf["recursive."]);
00125                 $this->config["storeRootPid"] = $this->conf["PIDstoreRoot"] ? $this->conf["PIDstoreRoot"] : $GLOBALS["TSFE"]->tmpl->rootLine[0][uid];
00126 
00127                         //extend standard search fields with user setup
00128                 $this->searchFieldList = trim($this->conf["stdSearchFieldExt"]) ? implode(",", array_unique(t3lib_div::trimExplode(",",$this->searchFieldList.",".trim($this->conf["stdSearchFieldExt"]),1))) : $this->searchFieldList;
00129 
00130                         // If the current record should be displayed.
00131                 $this->config["displayCurrentRecord"] = $this->conf["displayCurrentRecord"];
00132                 if ($this->config["displayCurrentRecord"])      {
00133                         $this->config["code"]="SINGLE";
00134                         $this->tt_product_single = true;
00135                 } else {
00136                         $this->tt_product_single = t3lib_div::_GET("tt_products");
00137                 }
00138 
00139                         // template file is fetched. The whole template file from which the various subpart are extracted.
00140                 $this->templateCode = $this->cObj->fileResource($this->conf["templateFile"]);
00141 
00142                         // globally substituted markers, fonts and colors.
00143                 $splitMark = md5(microtime());
00144                 $globalMarkerArray=array();
00145                 list($globalMarkerArray["###GW1B###"],$globalMarkerArray["###GW1E###"]) = explode($splitMark,$this->cObj->stdWrap($splitMark,$this->conf["wrap1."]));
00146                 list($globalMarkerArray["###GW2B###"],$globalMarkerArray["###GW2E###"]) = explode($splitMark,$this->cObj->stdWrap($splitMark,$this->conf["wrap2."]));
00147                 $globalMarkerArray["###GC1###"] = $this->cObj->stdWrap($this->conf["color1"],$this->conf["color1."]);
00148                 $globalMarkerArray["###GC2###"] = $this->cObj->stdWrap($this->conf["color2"],$this->conf["color2."]);
00149                 $globalMarkerArray["###GC3###"] = $this->cObj->stdWrap($this->conf["color3"],$this->conf["color3."]);
00150 
00151                         // Substitute Global Marker Array
00152                 $this->templateCode= $this->cObj->substituteMarkerArrayCached($this->templateCode, $globalMarkerArray);
00153 
00154 
00155                         // This cObject may be used to call a function which manipulates the shopping basket based on settings in an external order system. The output is included in the top of the order (HTML) on the basket-page.
00156                 $this->externalCObject = $this->getExternalCObject("externalProcessing");
00157 
00158                         // Initializes object
00159                 $this->setPidlist($this->config["pid_list"]);                           // The list of pid's we're operation on. All tt_products records must be in the pidlist in order to be selected.
00160                 $this->TAXpercentage = doubleval($this->conf["TAXpercentage"]);         // Set the TAX percentage.
00161                 $this->globalMarkerArray = $globalMarkerArray;
00162                 $this->initCategories();
00163                 $this->initBasket($GLOBALS["TSFE"]->fe_user->getKey("ses","recs"));     // Must do this to initialize the basket...
00164 
00165 
00166                 // *************************************
00167                 // *** Listing items:
00168                 // *************************************
00169 
00170                 $codes=t3lib_div::trimExplode(",", $this->config["code"]?$this->config["code"]:$this->conf["defaultCode"],1);
00171                 if (!count($codes))     $codes=array("");
00172                 while(list(,$theCode)=each($codes))     {
00173                         $theCode = (string)strtoupper(trim($theCode));
00174 
00175                         //      debug($theCode);
00176                         switch($theCode)        {
00177                                 case "TRACKING":
00178                                         $content.=$this->products_tracking($theCode);
00179                                 break;
00180                                 case "BASKET":
00181                                 case "PAYMENT":
00182                                 case "FINALIZE":
00183                                 case "INFO":
00184                                         $content.=$this->products_basket($theCode);
00185                                 break;
00186                                 case "SEARCH":
00187                                 case "SINGLE":
00188                                 case "LIST":
00189                                         $content.=$this->products_display($theCode);
00190                                 break;
00191                                 default:
00192                                         $langKey = strtoupper($GLOBALS["TSFE"]->config["config"]["language"]);
00193                                         $helpTemplate = $this->cObj->fileResource("EXT:tt_products/pi/products_help.tmpl");
00194 
00195                                                 // Get language version
00196                                         $helpTemplate_lang="";
00197                                         if ($langKey)   {$helpTemplate_lang = $this->cObj->getSubpart($helpTemplate,"###TEMPLATE_".$langKey."###");}
00198                                         $helpTemplate = $helpTemplate_lang ? $helpTemplate_lang : $this->cObj->getSubpart($helpTemplate,"###TEMPLATE_DEFAULT###");
00199 
00200                                                 // Markers and substitution:
00201                                         $markerArray["###CODE###"] = $theCode;
00202                                         $content.=$this->cObj->substituteMarkerArray($helpTemplate,$markerArray);
00203                                 break;
00204                         }
00205                 }
00206                 return $content;
00207         }
00208 
00212         function getExternalCObject($mConfKey)  {
00213                 if ($this->conf[$mConfKey] && $this->conf[$mConfKey."."])       {
00214                         $this->cObj->regObj = &$this;
00215                         return $this->cObj->cObjGetSingle($this->conf[$mConfKey],$this->conf[$mConfKey."."],"/".$mConfKey."/")."";
00216                 }
00217         }
00218 
00222         function products_tracking($theCode)    {
00223                 $admin = $this->shopAdmin();
00224                 if (t3lib_div::_GP("tracking") || $admin)       {               // Tracking number must be set
00225                         $orderRow = $this->getOrderRecord("",t3lib_div::_GP("tracking"));
00226                         if (is_array($orderRow) || $admin)      {               // If order is associated with tracking id.
00227                                 if (!is_array($orderRow))       $orderRow=array("uid"=>0);
00228                                 $content = $this->getTrackingInformation($orderRow,$this->templateCode);
00229                         } else {        // ... else output error page
00230                                 $content=$this->cObj->getSubpart($this->templateCode,$this->spMarker("###TRACKING_WRONG_NUMBER###"));
00231                                 if (!$GLOBALS["TSFE"]->beUserLogin)     {$content = $this->cObj->substituteSubpart($content,"###ADMIN_CONTROL###","");}
00232                         }
00233                 } else {        // No tracking number - show form with tracking number
00234                         $content=$this->cObj->getSubpart($this->templateCode,$this->spMarker("###TRACKING_ENTER_NUMBER###"));
00235                         if (!$GLOBALS["TSFE"]->beUserLogin)     {$content = $this->cObj->substituteSubpart($content,"###ADMIN_CONTROL###","");}
00236                 }
00237                 $markerArray=array();
00238                 $markerArray["###FORM_URL###"] = $this->getLinkUrl();   // Add FORM_URL to globalMarkerArray, linking to self.
00239                 $content= $this->cObj->substituteMarkerArray($content, $markerArray);
00240 
00241                 return $content;
00242         }
00243 
00247         function products_basket($theCode)      {
00248                 $this->setPidlist($this->config["storeRootPid"]);       // Set list of page id's to the storeRootPid.
00249                 $this->initRecursive(999);              // This add's all subpart ids to the pid_list based on the rootPid set in previous line
00250                 $this->generatePageArray();             // Creates an array with page titles from the internal pid_list. Used for the display of category titles.
00251 
00252                 if (count($this->basket))       {       // If there is content in the shopping basket, we are going display some basket code
00253                                 // prepare action
00254                         $activity="";
00255                         if (t3lib_div::_GP("products_info"))    {
00256                                 $activity="products_info";
00257                         } elseif (t3lib_div::_GP("products_payment"))   {
00258                                 $activity="products_payment";
00259                         } elseif (t3lib_div::_GP("products_finalize"))  {
00260                                 $activity="products_finalize";
00261                         }
00262 
00263                         if ($theCode=="INFO")   {
00264                                 $activity="products_info";
00265                         } elseif ($theCode=="PAYMENT")  {
00266                                 $activity="products_payment";
00267                         } elseif ($theCode=="FINALIZE") {
00268                                 $activity="products_finalize";
00269                         }
00270 
00271 //                      debug($activity);
00272                                 // perform action
00273                         switch($activity)       {
00274                                 case "products_info":
00275                                         $this->load_noLinkExtCobj();
00276                                         $content.=$this->getBasket("###BASKET_INFO_TEMPLATE###");
00277                                 break;
00278                                 case "products_payment":
00279                                         $this->load_noLinkExtCobj();
00280                                         if ($this->checkRequired())     {
00281                                                 $this->mapPersonIntoToDelivery();
00282                                                 $content=$this->getBasket("###BASKET_PAYMENT_TEMPLATE###");
00283                                         } else {        // If not all required info-fields are filled in, this is shown instead:
00284                                                 $content.=$this->cObj->getSubpart($this->templateCode,$this->spMarker("###BASKET_REQUIRED_INFO_MISSING###"));
00285                                                 $content = $this->cObj->substituteMarkerArray($content, $this->addURLMarkers(array()));
00286                                         }
00287                                 break;
00288                                 case "products_finalize":
00289                                         if ($this->checkRequired())     {
00290                                                 $this->load_noLinkExtCobj();
00291                                                 $this->mapPersonIntoToDelivery();
00292                                                 $handleScript = $GLOBALS["TSFE"]->tmpl->getFileName($this->basketExtra["payment."]["handleScript"]);
00293                                                 if ($handleScript)      {
00294                                                         $content = $this->includeHandleScript($handleScript,$this->basketExtra["payment."]["handleScript."]);
00295                                                 } else {
00296                                                         $orderUid = $this->getBlankOrderUid();
00297                                                         $content=$this->getBasket("###BASKET_ORDERCONFIRMATION_TEMPLATE###");
00298                                                         $this->finalizeOrder($orderUid);        // Important: finalizeOrder MUST come after the call of prodObj->getBasket, because this function, getBasket, calculates the order! And that information is used in the finalize-function
00299                                                 }
00300                                         } else {        // If not all required info-fields are filled in, this is shown instead:
00301                                                 $content.=$this->cObj->getSubpart($this->templateCode,$this->spMarker("###BASKET_REQUIRED_INFO_MISSING###"));
00302                                                 $content = $this->cObj->substituteMarkerArray($content, $this->addURLMarkers(array()));
00303                                         }
00304                                 break;
00305                                 default:
00306                                         $content.=$this->getBasket();
00307                                 break;
00308                         }
00309                 } else {
00310                         $content.=$this->cObj->getSubpart($this->templateCode,$this->spMarker("###BASKET_TEMPLATE_EMPTY###"));
00311                 }
00312                 $markerArray=array();
00313                 $markerArray["###EXTERNAL_COBJECT###"] = $this->externalCObject;        // adding extra preprocessing CObject
00314                 $content= $this->cObj->substituteMarkerArray($content, $markerArray);
00315 
00316                 return $content;
00317         }
00318         function load_noLinkExtCobj()   {
00319                 if ($this->conf["externalProcessing_final"] || is_array($this->conf["externalProcessing_final."]))      {       // If there is given another cObject for the final order confirmation template!
00320                         $this->externalCObject = $this->getExternalCObject("externalProcessing_final");
00321                 }
00322         }
00323 
00327         function spMarker($subpartMarker)       {
00328                 $sPBody = substr($subpartMarker,3,-3);
00329                 $altSPM = "";
00330                 if (isset($this->conf["altMainMarkers."]))      {
00331                         $altSPM = trim($this->cObj->stdWrap($this->conf["altMainMarkers."][$sPBody],$this->conf["altMainMarkers."][$sPBody."."]));
00332                         $GLOBALS["TT"]->setTSlogMessage("Using alternative subpart marker for '".$subpartMarker."': ".$altSPM,1);
00333                 }
00334                 return $altSPM ? $altSPM : $subpartMarker;
00335         }
00336 
00340         function products_display($theCode)     {
00341                 $formUrl = $this->getLinkUrl($this->conf["PIDbasket"]);
00342                 if ($this->tt_product_single)   {
00343         // List single product:
00344                                 // performing query:
00345                         $this->setPidlist($this->config["storeRootPid"]);
00346                         $this->initRecursive(999);
00347                         $this->generatePageArray();
00348 
00349                         $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_products', 'uid='.intval($this->tt_product_single).' AND pid IN ('.$this->pid_list.')'.$this->cObj->enableFields('tt_products'));
00350 
00351                         if($this->config["displayCurrentRecord"] || $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))         {
00352                                         // Get the subpart code
00353                                 $item ="";
00354                                 if ($this->config["displayCurrentRecord"])      {
00355                                         $row=$this->cObj->data;
00356                                         $item = trim($this->cObj->getSubpart($this->templateCode,$this->spMarker("###ITEM_SINGLE_DISPLAY_RECORDINSERT###")));
00357                                 }
00358                                 $catTitle= $this->pageArray[$row["pid"]]["title"].($row["category"]?"/".$this->categories[$row["category"]]:"");
00359                                 if (!$item)     {$item = $this->cObj->getSubpart($this->templateCode,$this->spMarker("###ITEM_SINGLE_DISPLAY###"));}
00360 
00361                                         // Fill marker arrays
00362                                 $wrappedSubpartArray=array();
00363                                 $wrappedSubpartArray["###LINK_ITEM###"]= array('<A href="'.$this->getLinkUrl(t3lib_div::_GP("backPID")).'">','</A>');
00364 
00365                                 $markerArray = $this->getItemMarkerArray ($row,$catTitle,10);
00366                                 $markerArray["###FORM_NAME###"]="item_".$this->tt_product_single;
00367                                 $markerArray["###FORM_URL###"]=$formUrl;
00368 
00369                                         // Substitute
00370                                 $content= $this->cObj->substituteMarkerArrayCached($item,$markerArray,array(),$wrappedSubpartArray);
00371                         }
00372                 } elseif ($theCode=="SINGLE") {
00373                         $content.="Wrong parameters, GET/POST var 'tt_products' was missing.";
00374                 } else {
00375                         $content="";
00376         // List products:
00377                         $where="";
00378                         if ($theCode=="SEARCH") {
00379                                         // Get search subpart
00380                                 $t["search"] = $this->cObj->getSubpart($this->templateCode,$this->spMarker("###ITEM_SEARCH###"));
00381                                         // Substitute a few markers
00382                                 $out=$t["search"];
00383                                 $out=$this->cObj->substituteMarker($out, "###FORM_URL###", $this->getLinkUrl($this->conf["PIDsearch"]));
00384                                 $out=$this->cObj->substituteMarker($out, "###SWORDS###", htmlspecialchars(t3lib_div::_GP("swords")));
00385                                         // Add to content
00386                                 $content.=$out;
00387                                 if (t3lib_div::_GP("swords"))   {
00388                                         $where = $this->searchWhere(trim(t3lib_div::_GP("swords")));
00389                                 }
00390                         }
00391                         $begin_at=t3lib_div::intInRange(t3lib_div::_GP("begin_at"),0,100000);
00392                         if (($theCode!="SEARCH" && !t3lib_div::_GP("swords")) || $where)        {
00393 
00394                                 $this->initRecursive($this->config["recursive"]);
00395                                 $this->generatePageArray();
00396 
00397                                         // Get products
00398                                 $selectConf = Array();
00399                                 $selectConf["pidInList"] = $this->pid_list;
00400                                 $selectConf["where"] = "1=1 ".$where;
00401 
00402                                         // performing query to count all products (we need to know it for browsing):
00403                                 $selectConf["selectFields"] = 'count(*)';
00404                                 $res = $this->cObj->exec_getQuery("tt_products",$selectConf);
00405                                 $row = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
00406                                 $productsCount = $row[0];
00407 
00408                                         // range check to current productsCount
00409                                 $begin_at = t3lib_div::intInRange(($begin_at >= $productsCount)?($productsCount-$this->config["limit"]):$begin_at,0);
00410 
00411                                         // performing query for display:
00412                                 $selectConf['orderBy'] = 'pid,category,title';
00413                                 $selectConf['selectFields'] = '*';
00414                                 $selectConf['max'] = ($this->config['limit']+1);
00415                                 $selectConf['begin'] = $begin_at;
00416 
00417                                 $res = $this->cObj->exec_getQuery('tt_products',$selectConf);
00418 
00419                                 $productsArray=array();
00420                                 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))               {
00421                                         $productsArray[$row["pid"]][]=$row;
00422                                 }
00423 
00424                                         // Getting various subparts we're going to use here:
00425                                 $t["listFrameWork"] = $this->cObj->getSubpart($this->templateCode,$this->spMarker("###ITEM_LIST_TEMPLATE###"));
00426                                 $t["categoryTitle"] = $this->cObj->getSubpart($t["listFrameWork"],"###ITEM_CATEGORY###");
00427                                 $t["itemFrameWork"] = $this->cObj->getSubpart($t["listFrameWork"],"###ITEM_LIST###");
00428                                 $t["item"] = $this->cObj->getSubpart($t["itemFrameWork"],"###ITEM_SINGLE###");
00429 
00430                                 $pageArr=explode(",",$this->pid_list);
00431                                 $currentP="";
00432                                 $out="";
00433                                 $iCount=0;
00434                                 $more=0;                // If set during this loop, the next-item is drawn
00435                                 while(list(,$v)=each($pageArr)) {
00436                                         if (is_array($productsArray[$v]))       {
00437                                                 reset($productsArray[$v]);
00438                                                 $itemsOut="";
00439                                                 while(list(,$row)=each($productsArray[$v]))     {
00440                                                         $iCount++;
00441                                                         if ($iCount>$this->config["limit"])     {
00442                                                                 $more=1;
00443                                                                 break;
00444                                                         }
00445 
00446 
00447                                                                 // Print Category Title
00448                                                         if ($row["pid"]."_".$row["category"]!=$currentP)        {
00449                                                                 if ($itemsOut)  {
00450                                                                         $out.=$this->cObj->substituteSubpart($t["itemFrameWork"], "###ITEM_SINGLE###", $itemsOut);
00451                                                                 }
00452                                                                 $itemsOut="";                   // Clear the item-code var
00453 
00454                                                                 $currentP = $row["pid"]."_".$row["category"];
00455                                                                 if ($where || $this->conf["displayListCatHeader"])      {
00456                                                                         $markerArray=array();
00457                                                                         $catTitle= $this->pageArray[$row["pid"]]["title"].($row["category"]?"/".$this->categories[$row["category"]]:"");
00458                                                                         $this->cObj->setCurrentVal($catTitle);
00459                                                                         $markerArray["###CATEGORY_TITLE###"]=$this->cObj->cObjGetSingle($this->conf["categoryHeader"],$this->conf["categoryHeader."], "categoryHeader");
00460                                                                         $out.= $this->cObj->substituteMarkerArray($t["categoryTitle"], $markerArray);
00461                                                                 }
00462                                                         }
00463 
00464                                                                 // Print Item Title
00465                                                         $wrappedSubpartArray=array();
00466                                                         $wrappedSubpartArray["###LINK_ITEM###"]= array('<A href="'.$this->getLinkUrl($this->conf["PIDitemDisplay"]).'&tt_products='.$row["uid"].'">','</A>');
00467                                                         $markerArray = $this->getItemMarkerArray ($row,$catTitle,1,"listImage");
00468                                                         $markerArray["###FORM_URL###"]=$formUrl; // Applied later as well.
00469                                                         $markerArray["###FORM_NAME###"]="item_".$iCount;
00470                                                         $itemsOut.= $this->cObj->substituteMarkerArrayCached($t["item"],$markerArray,array(),$wrappedSubpartArray);
00471                                                 }
00472                                                 if ($itemsOut)  {
00473                                                         $out.=$this->cObj->substituteMarkerArrayCached($t["itemFrameWork"], array(), array("###ITEM_SINGLE###"=>$itemsOut));
00474                                                 }
00475                                         }
00476                                 }
00477                         }
00478                         if ($out)       {
00479                                 // next / prev:
00480                                 $url = $this->getLinkUrl("","begin_at");
00481                                         // Reset:
00482                                 $subpartArray=array();
00483                                 $wrappedSubpartArray=array();
00484                                 $markerArray=array();
00485 
00486                                 if ($more)      {
00487                                         $next = ($begin_at+$this->config["limit"] > $productsCount) ? $productsCount-$this->config["limit"] : $begin_at+$this->config["limit"];
00488                                         $wrappedSubpartArray["###LINK_NEXT###"]=array('<A href="'.$url.'&begin_at='.$next.'">','</A>');
00489                                 } else {
00490                                         $subpartArray["###LINK_NEXT###"]="";
00491                                 }
00492                                 if ($begin_at)  {
00493                                         $prev = ($begin_at-$this->config["limit"] < 0) ? 0 : $begin_at-$this->config["limit"];
00494                                         $wrappedSubpartArray["###LINK_PREV###"]=array('<A href="'.$url.'&begin_at='.$prev.'">','</A>');
00495                                 } else {
00496                                         $subpartArray["###LINK_PREV###"]="";
00497                                 }
00498                                 if ($productsCount > $this->config["limit"] )   { // there is more than one page, so let's browse
00499                                         $wrappedSubpartArray["###LINK_BROWSE###"]=array('',''); // <- this could be done better I think, or not?
00500                                         $markerArray["###BROWSE_LINKS###"]="";
00501                                         for ($i = 0 ; $i < ($productsCount/$this->config["limit"]); $i++)       {
00502                                                 if (($begin_at >= $i*$this->config["limit"]) && ($begin_at < $i*$this->config["limit"]+$this->config["limit"]))         {
00503                                                         $markerArray["###BROWSE_LINKS###"].= ' <b>'.(string)($i+1).'</b> ';
00504                                                         //      you may use this if you want to link to the current page also
00505                                                         //      $markerArray["###BROWSE_LINKS###"].= ' <A href="'.$url.'&begin_at='.(string)($i * $this->config["limit"]).'"><b>'.(string)($i+1).'</b></A> ';
00506                                                 } else {
00507                                                         $markerArray["###BROWSE_LINKS###"].= ' <A href="'.$url.'&begin_at='.(string)($i * $this->config["limit"]).'">'.(string)($i+1).'</A> ';
00508                                                 }
00509                                         }
00510                                 } else {
00511                                         $subpartArray["###LINK_BROWSE###"]="";
00512                                 }
00513 
00514                                 $subpartArray["###ITEM_CATEGORY_AND_ITEMS###"]=$out;
00515                                 $markerArray["###FORM_URL###"]=$formUrl;      // Applied it here also...
00516                                 $markerArray["###ITEMS_SELECT_COUNT###"]=$productsCount;
00517 
00518                                 $content.= $this->cObj->substituteMarkerArrayCached($t["listFrameWork"],$markerArray,$subpartArray,$wrappedSubpartArray);
00519                         } elseif ($where)       {
00520                                 $content.=$this->cObj->getSubpart($this->templateCode,$this->spMarker("###ITEM_SEARCH_EMPTY###"));
00521                         }
00522                 }
00523                 return $content;
00524         }
00525 
00529         function setPidlist($pid_list)  {
00530                 $this->pid_list = $pid_list;
00531         }
00532 
00536         function initRecursive($recursive)      {
00537                 if ($recursive) {               // get pid-list if recursivity is enabled
00538                         $pid_list_arr = explode(",",$this->pid_list);
00539                         $this->pid_list="";
00540                         while(list(,$val)=each($pid_list_arr))  {
00541                                 $this->pid_list.=$val.",".$this->cObj->getTreeList($val,intval($recursive));
00542                         }
00543                         $this->pid_list = ereg_replace(",$","",$this->pid_list);
00544                 }
00545         }
00546 
00550         function initCategories()       {
00551                         // Fetching catagories:
00552                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'tt_products_cat', '1=1'.$this->cObj->enableFields('tt_products_cat'));
00553                 $this->categories = array();
00554                 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))       {
00555                         $this->categories[$row["uid"]] = $row["title"];
00556                 }
00557         }
00558 
00562         function generatePageArray()    {
00563                         // Get pages (for category titles)
00564                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('title,uid', 'pages', 'uid IN ('.$this->pid_list.')');
00565                 $this->pageArray = array();
00566                 while($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))               {
00567                         $this->pageArray[$row["uid"]] = $row;
00568                 }
00569         }
00570 
00576         function initBasket($basket)    {
00577                 $this->recs = $basket;  // Sets it internally
00578                 $this->basket=array();
00579                 $uidArr=array();
00580                 if (is_array($basket["tt_products"]))   {
00581                         reset($basket["tt_products"]);
00582                         while(list($uid,$count)=each($basket["tt_products"]))   {
00583                                 if (t3lib_div::testInt($uid))   {
00584                                         $count=t3lib_div::intInRange($count,0,100000);
00585                                         if ($count)     {
00586                                                 $this->basket[$uid]=$count;
00587                                                 $uidArr[]=$uid;
00588                                         }
00589                                 }
00590                         }
00591                 }
00592                 $this->uid_list=implode($uidArr,",");
00593                 $this->setBasketExtras($basket);
00594 
00595                 $this->personInfo = $basket["personinfo"];
00596                 $this->deliveryInfo = $basket["delivery"];
00597                 if ($GLOBALS["TSFE"]->loginUser && (!$this->personInfo || $this->conf["lockLoginUserInfo"]))    {
00598                         $address = implode(chr(10),t3lib_div::trimExplode(chr(10),
00599                                 $GLOBALS["TSFE"]->fe_user->user["address"].chr(10).
00600                                 $GLOBALS["TSFE"]->fe_user->user["zip"]." ".$GLOBALS["TSFE"]->fe_user->user["city"].chr(10).
00601                                 $GLOBALS["TSFE"]->fe_user->user["country"]
00602                                 ,1)
00603                         );
00604 
00605                         $this->personInfo["name"] = $GLOBALS["TSFE"]->fe_user->user["name"];
00606                         $this->personInfo["address"] = $address;
00607                         $this->personInfo["email"] = $GLOBALS["TSFE"]->fe_user->user["email"];
00608                         $this->personInfo["telephone"] = $GLOBALS["TSFE"]->fe_user->user["telephone"];
00609                         $this->personInfo["fax"] = $GLOBALS["TSFE"]->fe_user->user["fax"];
00610                 }
00611         }
00612 
00616         function checkExtraAvailable($name,$key)        {
00617                 if (is_array($this->conf[$name."."][$key."."]) && (!isset($this->conf[$name."."][$key."."]["show"]) || $this->conf[$name."."][$key."."]["show"]))       {
00618                         return true;
00619                 }
00620         }
00621 
00625         function setBasketExtras($basket)       {
00626                         // shipping
00627                 ksort($this->conf["shipping."]);
00628                 reset($this->conf["shipping."]);
00629                 $k=intval($basket["tt_products"]["shipping"]);
00630                 if (!$this->checkExtraAvailable("shipping",$k)) {
00631                         $k=intval(key($this->cleanConfArr($this->conf["shipping."],1)));
00632                 }
00633                 $this->basketExtra["shipping"] = $k;
00634                 $this->basketExtra["shipping."] = $this->conf["shipping."][$k."."];
00635                 $excludePayment = trim($this->basketExtra["shipping."]["excludePayment"]);
00636 
00637                         // payment
00638                 if ($excludePayment)    {
00639                         $exclArr = t3lib_div::intExplode(",",$excludePayment);
00640                         while(list(,$theVal)=each($exclArr))    {
00641                                 unset($this->conf["payment."][$theVal]);
00642                                 unset($this->conf["payment."][$theVal."."]);
00643                         }
00644                 }
00645 
00646                 ksort($this->conf["payment."]);
00647                 reset($this->conf["payment."]);
00648                 $k=intval($basket["tt_products"]["payment"]);
00649                 if (!$this->checkExtraAvailable("payment",$k))  {
00650                         $k=intval(key($this->cleanConfArr($this->conf["payment."],1)));
00651                 }
00652                 $this->basketExtra["payment"] = $k;
00653                 $this->basketExtra["payment."] = $this->conf["payment."][$k."."];
00654 
00655 //              debug($this->basketExtra);
00656 //              debug($this->conf);
00657         }
00658 
00662         function getClearBasketRecord() {
00663                         // Returns a basket-record cleared of tt_product items
00664                 unset($this->recs["tt_products"]);
00665                 return ($this->recs);
00666         }
00667 
00668 
00669 
00670 
00671 
00672 
00673 
00674         // **************************
00675         // ORDER related functions
00676         // **************************
00677 
00684         function createOrder()  {
00685                 $newId = 0;
00686                 $pid = intval($this->conf["PID_sys_products_orders"]);
00687                 if (!$pid)      $pid = intval($GLOBALS["TSFE"]->id);
00688                 if ($GLOBALS["TSFE"]->sys_page->getPage_noCheck ($pid)) {
00689                         $advanceUid = 0;
00690                         if ($this->conf["advanceOrderNumberWithInteger"])       {
00691                                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'sys_products_orders', '', '', 'uid DESC', '1');
00692                                 list($prevUid) = $GLOBALS['TYPO3_DB']->sql_fetch_row($res);
00693 
00694                                 $rndParts = explode(",",$this->conf["advanceOrderNumberWithInteger"]);
00695                                 $advanceUid = $prevUid+t3lib_div::intInRange(rand(intval($rndParts[0]),intval($rndParts[1])),1);
00696                         }
00697 
00698                         $insertFields = array(
00699                                 'pid' => $pid,
00700                                 'tstamp' => time(),
00701                                 'crdate' => time(),
00702                                 'deleted' => 1
00703                         );
00704                         if ($advanceUid > 0)    {
00705                                 $insertFields['uid'] = $advanceUid;
00706                         }
00707 
00708                         $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_products_orders', $insertFields);
00709 
00710                         $newId = $GLOBALS['TYPO3_DB']->sql_insert_id();
00711                 }
00712                 return $newId;
00713         }
00714 
00722         function getBlankOrderUid()     {
00723                 $orderUid = intval($this->recs["tt_products"]["orderUid"]);
00724                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('uid', 'sys_products_orders', 'uid='.intval($orderUid).' AND deleted!=0 AND status=0');   // Checks if record exists, is marked deleted (all blank orders are deleted by default) and is not finished.
00725                 if (!$GLOBALS['TYPO3_DB']->sql_num_rows($res))  {
00726                         $orderUid = $this->createOrder();
00727                         $this->recs["tt_products"]["orderUid"] = $orderUid;
00728                         $this->recs["tt_products"]["orderDate"] = time();
00729                         $this->recs["tt_products"]["orderTrackingNo"] = $this->getOrderNumber($orderUid)."-".strtolower(substr(md5(uniqid(time())),0,6));
00730                         $GLOBALS["TSFE"]->fe_user->setKey("ses","recs",$this->recs);
00731                 }
00732                 return $orderUid;
00733         }
00734 
00739         function getOrderRecord($orderUid,$tracking='') {
00740                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_products_orders', ($tracking ? 'tracking_code='.$GLOBALS['TYPO3_DB']->fullQuoteStr($tracking, 'sys_products_orders') : 'uid='.intval($orderUid)).' AND deleted=0');
00741                 return $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
00742         }
00743 
00748         function getOrderNumber($orderUid)      {
00749                 return substr($this->conf["orderNumberPrefix"],0,10).$orderUid;
00750         }
00751 
00761         function finalizeOrder($orderUid,$mainMarkerArray=array())      {
00762                         // Fix delivery address
00763                 $this->mapPersonIntoToDelivery();       // This maps the billing address into the blank fields of the delivery address
00764                 $mainMarkerArray["###EXTERNAL_COBJECT###"] = $this->externalCObject."";
00765                 $orderConfirmationHTML=trim($this->getBasket("###BASKET_ORDERCONFIRMATION_TEMPLATE###","",$mainMarkerArray));           // Getting the template subpart for the order confirmation!
00766 
00767                         // Saving order data
00768                 $fieldsArray=array();
00769                 $fieldsArray["note"]=$this->deliveryInfo["note"];
00770                 $fieldsArray["name"]=$this->deliveryInfo["name"];
00771                 $fieldsArray["telephone"]=$this->deliveryInfo["telephone"];
00772                 $fieldsArray["email"]=$this->deliveryInfo["email"];
00773                 $fieldsArray["email_notify"]=  $this->conf["email_notify_default"];             // Email notification is set here. Default email address is delivery email contact
00774 
00775                         // can be changed after order is set.
00776                 $fieldsArray["payment"]=$this->basketExtra["payment"].": ".$this->basketExtra["payment."]["title"];
00777                 $fieldsArray["shipping"]=$this->basketExtra["shipping"].": ".$this->basketExtra["shipping."]["title"];
00778                 $fieldsArray["amount"]=$this->calculatedSums_tax["total"];
00779                 $fieldsArray["status"]=1;       // This means, "Order confirmed on website, next step: confirm from shop that order is received"
00780 
00781                                 // Default status_log entry
00782                 $status_log=array();
00783                 $status_log[] = array(
00784                         "time" => time(),
00785                         "info" => $this->conf["statusCodes."][$fieldsArray["status"]],
00786                         "status" => $fieldsArray["status"],
00787                         "comment" => $this->deliveryInfo["note"]
00788                 );
00789                 $fieldsArray["status_log"]=serialize($status_log);
00790 
00791                         // Order Data serialized
00792                 $fieldsArray["orderData"]=serialize(array(
00793                                 "html_output"                   => $orderConfirmationHTML,
00794                                 "deliveryInfo"                  => $this->deliveryInfo,
00795                                 "personInfo"                    => $this->personInfo,
00796                                 "calculatedBasket"              =>      $this->calculatedBasket,
00797                                 "calculatedSum_tax"             =>      $this->calculatedSums_tax,
00798                                 "calculatedSums_no_tax" =>      $this->calculatedSums_no_tax
00799                 ));
00800 
00801                         // Setting tstamp, deleted and tracking code
00802                 $fieldsArray["tstamp"]=time();
00803                 $fieldsArray["deleted"]=0;
00804                 $fieldsArray["tracking_code"]=$this->recs["tt_products"]["orderTrackingNo"];
00805 
00806                         // Saving the order record
00807                 $GLOBALS['TYPO3_DB']->exec_UPDATEquery('sys_products_orders', 'uid='.intval($orderUid), $fieldsArray);
00808 
00809                         // Fetching the orderRecord by selecing the newly saved one...
00810                 $this->orderRecord = $this->getOrderRecord($orderUid);
00811 
00812 
00813                         // Creates M-M relations for the products with tt_products table. Isn't really used yet, but later will be used to display stock-status by looking up how many items are already ordered.
00814                         // First: delete any existing. Shouldn't be any
00815                 $GLOBALS['TYPO3_DB']->exec_DELETEquery('sys_products_orders_mm_tt_products', 'sys_products_orders_uid='.intval($orderUid));
00816 
00817                         // Second: Insert a new relation for each ordered item
00818                 reset($this->calculatedBasket);
00819                 while(list(,$itemInfo)=each($this->calculatedBasket))   {
00820                         $insertFields = array(
00821                                 'sys_products_orders_uid' => $orderUid,
00822                                 'sys_products_orders_qty' => intval($itemInfo['count']),
00823                                 'tt_products_uid' => intval($itemInfo['rec']['uid'])
00824                         );
00825                         $GLOBALS['TYPO3_DB']->exec_INSERTquery('sys_products_orders_mm_tt_products', $insertFields);
00826                 }
00827 
00828                         // Sends order emails:
00829                 $headers=array();
00830                 if ($this->conf["orderEmail_from"])     {$headers[]="FROM: ".$this->conf["orderEmail_fromName"]." <".$this->conf["orderEmail_from"].">";}
00831 
00832                 $recipients = $this->conf["orderEmail_to"];
00833                 $recipients.=",".$this->deliveryInfo["email"];
00834                 $recipients=t3lib_div::trimExplode(",",$recipients,1);
00835 
00836                 if (count($recipients)) {       // If any recipients, then compile and send the mail.
00837                         $emailContent=trim($this->getBasket("###EMAIL_PLAINTEXT_TEMPLATE###"));
00838                         if ($emailContent)      {               // If there is plain text content - which is required!!
00839                                 $parts = split(chr(10),$emailContent,2);                // First line is subject
00840                                 $subject=trim($parts[0]);
00841                                 $plain_message=trim($parts[1]);
00842 
00843 
00844                                 $cls  = t3lib_div::makeInstanceClassName("tt_products_htmlmail");
00845                                 if (class_exists($cls) && $this->conf["orderEmail_htmlmail"])   {       // If htmlmail lib is included, then generate a nice HTML-email
00846                                         $HTMLmailShell=$this->cObj->getSubpart($this->templateCode,"###EMAIL_HTML_SHELL###");
00847                                         $HTMLmailContent=$this->cObj->substituteMarker($HTMLmailShell,"###HTML_BODY###",$orderConfirmationHTML);
00848                                         $HTMLmailContent=$this->cObj->substituteMarkerArray($HTMLmailContent, $this->globalMarkerArray);
00849 
00850 
00851                                                 // Remove image tags to products:
00852                                         if ($this->conf["orderEmail_htmlmail."]["removeImagesWithPrefix"])      {
00853                                                 $parser = t3lib_div::makeInstance("t3lib_parsehtml");
00854                                                 $htmlMailParts = $parser->splitTags("img",$HTMLmailContent);
00855 
00856                                                 reset($htmlMailParts);
00857                                                 while(list($kkk,$vvv)=each($htmlMailParts))     {
00858                                                         if ($kkk%2)     {
00859                                                                 list($attrib) = $parser->get_tag_attributes($vvv);
00860                                                                 if (t3lib_div::isFirstPartOfStr($attrib["src"],$this->conf["orderEmail_htmlmail."]["removeImagesWithPrefix"]))  {
00861 #debug($htmlMailParts[$kkk]);
00862                                                                         $htmlMailParts[$kkk]="";
00863                                                                 }
00864                                                         }
00865                                                 }
00866                                                 $HTMLmailContent=implode("",$htmlMailParts);
00867                                         }
00868 
00869                                         $V = array (
00870                                                 "from_email" => $this->conf["orderEmail_from"],
00871                                                 "from_name" => $this->conf["orderEmail_fromName"]
00872                                         );
00873 
00874                                         $Typo3_htmlmail = t3lib_div::makeInstance("tt_products_htmlmail");
00875                                         $Typo3_htmlmail->useBase64();
00876                                         $Typo3_htmlmail->start(implode($recipients,","), $subject, $plain_message, $HTMLmailContent, $V);
00877 //echo $HTMLmailContent;
00878 //                                              debug($Typo3_htmlmail->message);
00879 //                                              debug($Typo3_htmlmail->recipient);
00880 //                                              debug($Typo3_htmlmail->theParts);
00881                                                 $Typo3_htmlmail->sendtheMail();
00882 
00883                                                 //debug($HTMLmailContent);
00884                                 } else {                // ... else just plain text...
00885                                         $GLOBALS["TSFE"]->plainMailEncoded(implode($recipients,","), $subject, $plain_message, implode($headers,chr(10)));
00886                                 }
00887                         }
00888                 }
00889 
00890                         // Empties the shopping basket!
00891                 $GLOBALS["TSFE"]->fe_user->setKey("ses","recs",$this->getClearBasketRecord());
00892 
00893                         // This cObject may be used to call a function which clears settings in an external order system.
00894                         // The output is NOT included anywhere
00895                 $this->getExternalCObject("externalFinalizing");
00896         }
00897 
00898 
00899 
00900 
00901 
00902 
00903         // **************************
00904         // Utility functions
00905         // **************************
00906 
00907 
00911         function getPrice($price,$tax=1)        {
00912                 $taxFactor = 1+$this->TAXpercentage/100;
00913                 $taxIncluded = $this->conf["TAXincluded"];
00914                 if ($tax)       {
00915                         if ($taxIncluded)       {       // If the configuration says that prices in the database is with tax included
00916                                 return doubleval($price);
00917                         } else {
00918                                 return doubleval($price)*$taxFactor;
00919                         }
00920                 } else {
00921                         if ($taxIncluded)       {       // If the configuration says that prices in the database is with tax included
00922                                 return doubleval($price)/$taxFactor;
00923                         } else {
00924                                 return doubleval($price);
00925                         }
00926                 }
00927         }
00928 
00932         function searchWhere($sw)       {
00933                 $where=$this->cObj->searchWhere($sw, $this->searchFieldList, 'tt_products');
00934                 return $where;
00935         }
00936 
00940         function getLinkUrl($id="",$excludeList="")     {
00941                 $queryString=array();
00942                 $queryString["id"] = ($id ? $id : $GLOBALS["TSFE"]->id);
00943                 $queryString["type"]= $GLOBALS["TSFE"]->type ? 'type='.$GLOBALS["TSFE"]->type : "";
00944                 $queryString["backPID"]= 'backPID='.$GLOBALS["TSFE"]->id;
00945                 $queryString["begin_at"]= t3lib_div::_GP("begin_at") ? 'begin_at='.t3lib_div::_GP("begin_at") : "";
00946                 $queryString["swords"]= t3lib_div::_GP("swords") ? "swords=".rawurlencode(t3lib_div::_GP("swords")) : "";
00947 
00948                 reset($queryString);
00949                 while(list($key,$val)=each($queryString))       {
00950                         if (!$val || ($excludeList && t3lib_div::inList($excludeList,$key)))    {
00951                                 unset($queryString[$key]);
00952                         }
00953                 }
00954                 return $GLOBALS["TSFE"]->absRefPrefix.'index.php?'.implode($queryString,"&");
00955         }
00956 
00960         function priceFormat($double)   {
00961                 return number_format($double,intval($this->conf["priceDec"]),$this->conf["priceDecPoint"],$this->conf["priceThousandPoint"]);
00962         }
00963 
00967         function mapPersonIntoToDelivery()      {
00968                 $infoFields = explode(",","name,address,telephone,fax,email,company,city,zip,state,country");
00969                 while(list(,$fName)=each($infoFields))  {
00970                         if (!trim($this->deliveryInfo[$fName])) {
00971                                 $this->deliveryInfo[$fName] = $this->personInfo[$fName];
00972                         }
00973                 }
00974         }
00975 
00979         function checkRequired()        {
00980                 $flag=1;
00981                 if (trim($this->conf["requiredInfoFields"]))    {
00982                         $infoFields = t3lib_div::trimExplode(",",$this->conf["requiredInfoFields"]);
00983                         while(list(,$fName)=each($infoFields))  {
00984                                 if (!trim($this->personInfo[$fName]))   {
00985                                         $flag=0;
00986                                         break;
00987                                 }
00988                         }
00989                 }
00990                 return $flag;
00991         }
00992 
00996         function includeCalcScript($calcScript,$conf)   {
00997                 include($calcScript);
00998         }
00999 
01003         function includeHandleScript($handleScript,$conf)       {
01004                 include($handleScript);
01005                 return $content;
01006         }
01007 
01008 
01009 
01010 
01011 
01012 
01013 
01014         // **************************
01015         // Template marker substitution
01016         // **************************
01017 
01021         function getItemMarkerArray ($row,$catTitle, $imageNum=0, $imageRenderObj="image")      {
01022                         // Returns a markerArray ready for substitution with information for the tt_producst record, $row
01023                 $markerArray=array();
01024                         // Get image
01025                 $theImgCode="";
01026                 $imgs = explode(",",$row["image"]);
01027