00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 include_once( "kernel/classes/ezpersistentobject.php" );
00040 include_once( "kernel/classes/ezproductcollection.php" );
00041 include_once( "kernel/classes/ezproductcollectionitem.php" );
00042 include_once( "kernel/classes/datatypes/ezuser/ezuser.php" );
00043 include_once( "kernel/classes/ezuserdiscountrule.php" );
00044 include_once( "kernel/classes/ezcontentobjecttreenode.php" );
00045 include_once( "kernel/classes/ezshippingmanager.php" );
00046 include_once( "kernel/classes/ezorder.php" );
00047
00048
00049
00050
00051 define( "EZ_BASKET_ITEM_LIMIT", 3000 );
00052
00053 class eZBasket extends eZPersistentObject
00054 {
00055
00056
00057 function eZBasket( $row )
00058 {
00059 $this->eZPersistentObject( $row );
00060 }
00061
00062
00063
00064
00065 function definition()
00066 {
00067 return array( "fields" => array( "id" => array( 'name' => 'ID',
00068 'datatype' => 'integer',
00069 'default' => 0,
00070 'required' => true ),
00071 "session_id" => array( 'name' => "SessionID",
00072 'datatype' => 'string',
00073 'default' => '',
00074 'required' => true ),
00075 "productcollection_id" => array( 'name' => "ProductCollectionID",
00076 'datatype' => 'integer',
00077 'default' => '0',
00078 'required' => true,
00079 'foreign_class' => 'eZProductCollection',
00080 'foreign_attribute' => 'id',
00081 'multiplicity' => '1..*' ),
00082 "order_id" => array( 'name' => "OrderID",
00083 'datatype' => 'integer',
00084 'default' => 0,
00085 'required' => false,
00086 'foreign_class' => 'eZOrder',
00087 'foreign_attribute' => 'id',
00088 'multiplicity' => '1..*') ),
00089 'function_attributes' => array( 'items' => 'items',
00090 'total_ex_vat' => 'totalExVAT',
00091 'total_inc_vat' => 'totalIncVAT',
00092 'is_empty' => 'isEmpty',
00093 'productcollection' => 'productCollection',
00094 'items_info' => 'itemsInfo' ),
00095 "keys" => array( "id" ),
00096 "increment_key" => "id",
00097 "class_name" => "eZBasket",
00098 "name" => "ezbasket" );
00099 }
00100
00101 function &items( $asObject = true )
00102 {
00103 $productItems = eZPersistentObject::fetchObjectList( eZProductCollectionItem::definition(),
00104 null,
00105 array( 'productcollection_id' => $this->ProductCollectionID ),
00106 array( 'contentobject_id' => 'desc' ),
00107 null,
00108 $asObject );
00109 $addedProducts = array();
00110 foreach ( $productItems as $productItem )
00111 {
00112 $discountPercent = 0.0;
00113 $isVATIncluded = true;
00114 $id = $productItem->attribute( 'id' );
00115 $contentObject = $productItem->attribute( 'contentobject' );
00116
00117 if ( $contentObject !== null )
00118 {
00119 $vatValue = $productItem->attribute( 'vat_value' );
00120
00121
00122 $realVatValue = $vatValue;
00123 if ( $vatValue == -1 )
00124 $vatValue = 0;
00125
00126 $count = $productItem->attribute( 'item_count' );
00127 $discountPercent = $productItem->attribute( 'discount' );
00128 $nodeID = $contentObject->attribute( 'main_node_id' );
00129 $objectName = $contentObject->attribute( 'name' );
00130
00131 $isVATIncluded = $productItem->attribute( 'is_vat_inc' );
00132 $price = $productItem->attribute( 'price' );
00133
00134 if ( $isVATIncluded )
00135 {
00136 $priceExVAT = $price / ( 100 + $vatValue ) * 100;
00137 $priceIncVAT = $price;
00138 $totalPriceExVAT = $count * $priceExVAT * ( 100 - $discountPercent ) / 100;
00139 $totalPriceIncVAT = $count * $priceIncVAT * ( 100 - $discountPercent ) / 100 ;
00140 }
00141 else
00142 {
00143 $priceExVAT = $price;
00144 $priceIncVAT = $price * ( 100 + $vatValue ) / 100;
00145 $totalPriceExVAT = $count * $priceExVAT * ( 100 - $discountPercent ) / 100;
00146 $totalPriceIncVAT = $count * $priceIncVAT * ( 100 - $discountPercent ) / 100 ;
00147 }
00148
00149 $addedProduct = array( "id" => $id,
00150 "vat_value" => $realVatValue,
00151 "item_count" => $count,
00152 "node_id" => $nodeID,
00153 "object_name" => $objectName,
00154 "price_ex_vat" => $priceExVAT,
00155 "price_inc_vat" => $priceIncVAT,
00156 "discount_percent" => $discountPercent,
00157 "total_price_ex_vat" => $totalPriceExVAT,
00158 "total_price_inc_vat" => $totalPriceIncVAT,
00159 'item_object' => $productItem );
00160 $addedProducts[] = $addedProduct;
00161 }
00162 }
00163 return $addedProducts;
00164 }
00165
00166
00167
00168 function &itemsInfo()
00169 {
00170 $basketInfo = array();
00171
00172 $items =& $this->items();
00173 foreach ( $items as $item )
00174 {
00175 $vatValue = $item['vat_value'];
00176 $itemCount = abs( $item['item_count'] );
00177 $priceExVAT = $item['price_ex_vat'];
00178 $priceIncVAT = $item['price_inc_vat'];
00179 $totalPriceExVAT = $item['total_price_ex_vat'];
00180 $totalPriceIncVAT = $item['total_price_inc_vat'];
00181
00182 if ( !isset( $basketInfo['price_info'][$vatValue]['price_ex_vat'] ) )
00183 {
00184 $basketInfo['price_info'][$vatValue]['price_ex_vat'] = ( $priceExVAT * $itemCount );
00185 $basketInfo['price_info'][$vatValue]['price_inc_vat'] = ( $priceIncVAT * $itemCount );
00186 $basketInfo['price_info'][$vatValue]['price_vat'] = ( $priceIncVAT - $priceExVAT ) * $itemCount;
00187
00188 $basketInfo['price_info'][$vatValue]['total_price_ex_vat'] = $totalPriceExVAT;
00189 $basketInfo['price_info'][$vatValue]['total_price_inc_vat'] = $totalPriceIncVAT;
00190 $basketInfo['price_info'][$vatValue]['total_price_vat'] = $totalPriceIncVAT - $totalPriceExVAT;
00191 }
00192 else
00193 {
00194 $basketInfo['price_info'][$vatValue]['price_ex_vat'] += ( $priceExVAT * $itemCount );
00195 $basketInfo['price_info'][$vatValue]['price_inc_vat'] += ( $priceIncVAT * $itemCount );
00196 $basketInfo['price_info'][$vatValue]['price_vat'] += ( $priceIncVAT - $priceExVAT ) * $itemCount;
00197
00198 $basketInfo['price_info'][$vatValue]['total_price_ex_vat'] += $totalPriceExVAT;
00199 $basketInfo['price_info'][$vatValue]['total_price_inc_vat'] += $totalPriceIncVAT;
00200 $basketInfo['price_info'][$vatValue]['total_price_vat'] += ( $totalPriceIncVAT - $totalPriceExVAT );
00201 }
00202
00203 if ( !isset( $basketInfo['total_price_info']['total_price_ex_vat'] ) )
00204 {
00205 $basketInfo['total_price_info']['price_ex_vat'] = ( $priceExVAT * $itemCount );
00206 $basketInfo['total_price_info']['price_inc_vat'] = ( $priceIncVAT * $itemCount );
00207 $basketInfo['total_price_info']['price_vat'] = ( ( $priceIncVAT - $priceExVAT ) * $itemCount );
00208
00209 $basketInfo['total_price_info']['total_price_ex_vat'] = $totalPriceExVAT;
00210 $basketInfo['total_price_info']['total_price_inc_vat'] = $totalPriceIncVAT;
00211 $basketInfo['total_price_info']['total_price_vat'] = ( $totalPriceIncVAT - $totalPriceExVAT );
00212 }
00213 else
00214 {
00215 $basketInfo['total_price_info']['price_ex_vat'] += ( $priceExVAT * $itemCount );
00216 $basketInfo['total_price_info']['price_inc_vat'] += ( $priceIncVAT * $itemCount );
00217 $basketInfo['total_price_info']['price_vat'] += ( ( $priceIncVAT - $priceExVAT ) * $itemCount );
00218
00219 $basketInfo['total_price_info']['total_price_ex_vat'] += $totalPriceExVAT;
00220 $basketInfo['total_price_info']['total_price_inc_vat'] += $totalPriceIncVAT;
00221 $basketInfo['total_price_info']['total_price_vat'] += ( $totalPriceIncVAT - $totalPriceExVAT );
00222 }
00223 }
00224
00225
00226 $productCollectionID = $this->attribute( 'productcollection_id' );
00227
00228
00229 $shippingUpdateStatus = eZShippingManager::updatePriceInfo( $productCollectionID, $basketInfo );
00230
00231 ksort( $basketInfo['price_info'] );
00232 return $basketInfo;
00233 }
00234
00235
00236
00237
00238
00239
00240 function isVATKnown()
00241 {
00242 $result = true;
00243 foreach ( $this->items() as $item )
00244 {
00245 if ( $item['vat_value'] == -1 )
00246 return false;
00247 }
00248
00249 return true;
00250 }
00251
00252 function &totalIncVAT()
00253 {
00254 $items =& $this->items();
00255
00256 $total = 0.0;
00257 foreach ( $items as $item )
00258 {
00259 $total += $item['total_price_inc_vat'];
00260 }
00261 return $total;
00262 }
00263
00264 function &totalExVAT()
00265 {
00266 $items =& $this->items();
00267
00268 $total = 0.0;
00269 foreach ( $items as $item )
00270 {
00271 $total += $item['total_price_ex_vat'];
00272 }
00273 return $total;
00274 }
00275
00276
00277
00278
00279
00280 function removeItem( $itemID )
00281 {
00282 $item = eZProductCollectionItem::fetch( $itemID );
00283 if ( is_object( $item ) && $this->attribute( 'productcollection_id' ) == $item->attribute( 'productcollection_id' ) )
00284 {
00285 $item->remove();
00286 }
00287 }
00288
00289 function &isEmpty()
00290 {
00291 $items = $this->items();
00292 if ( count( $items ) > 0 )
00293 {
00294 $result = false;
00295 }
00296 else
00297 {
00298 $result = true;
00299 }
00300
00301 return $result;
00302 }
00303
00304
00305
00306
00307
00308
00309 function &fetch( $sessionKey )
00310 {
00311 $basket = eZPersistentObject::fetchObject( eZBasket::definition(),
00312 null, array( "session_id" => $sessionKey ),
00313 true );
00314 return $basket;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323 function ¤tBasket( $asObject=true, $byOrderID=-1 )
00324 {
00325 $basketList = array();
00326
00327 if( $byOrderID != -1 )
00328 {
00329 $basketList = eZPersistentObject::fetchObjectList( eZBasket::definition(),
00330 null, array( "order_id" => $byOrderID ),
00331 null, null,
00332 $asObject );
00333 }
00334 else
00335 {
00336 $http =& eZHTTPTool::instance();
00337 $sessionID = $http->sessionID();
00338
00339 $basketList = eZPersistentObject::fetchObjectList( eZBasket::definition(),
00340 null, array( "session_id" => $sessionID ),
00341 null, null,
00342 $asObject );
00343 }
00344
00345 $currentBasket = false;
00346 if ( count( $basketList ) == 0 )
00347 {
00348 $db =& eZDB::instance();
00349 $db->begin();
00350 $collection = eZProductCollection::create();
00351 $collection->store();
00352
00353 $currentBasket = new eZBasket( array( "session_id" => $sessionID,
00354 "productcollection_id" => $collection->attribute( "id" ) ) );
00355 $currentBasket->store();
00356 $db->commit();
00357 }
00358 else
00359 {
00360 $currentBasket =& $basketList[0];
00361 }
00362 return $currentBasket;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 function createOrder()
00372 {
00373
00374 $productCollectionID = $this->attribute( 'productcollection_id' );
00375
00376 $user =& eZUser::currentUser();
00377 $userID = $user->attribute( 'contentobject_id' );
00378
00379 include_once( 'kernel/classes/ezorderstatus.php' );
00380 $time = mktime();
00381 $order = new eZOrder( array( 'productcollection_id' => $productCollectionID,
00382 'user_id' => $userID,
00383 'is_temporary' => 1,
00384 'created' => $time,
00385 'status_id' => EZ_ORDER_STATUS_PENDING,
00386 'status_modified' => $time,
00387 'status_modifier_id' => $userID
00388 ) );
00389
00390 $db =& eZDB::instance();
00391 $db->begin();
00392 $order->store();
00393
00394 $orderID = $order->attribute( 'id' );
00395 $this->setAttribute( 'order_id', $orderID );
00396 $this->store();
00397 $db->commit();
00398
00399 return $order;
00400 }
00401
00402
00403
00404
00405
00406 function updatePrices()
00407 {
00408 $productCollection =& $this->attribute( 'productcollection' );
00409 if ( $productCollection )
00410 {
00411 include_once( 'kernel/shop/classes/ezshopfunctions.php' );
00412
00413 $currencyCode = '';
00414 $items =& $this->items();
00415
00416 $db =& eZDB::instance();
00417 $db->begin();
00418 foreach( array_keys( $items ) as $key )
00419 {
00420 $itemArray =& $items[ $key ];
00421 $item =& $itemArray['item_object'];
00422 $productContentObject =& $item->attribute( 'contentobject' );
00423 $priceObj = null;
00424 $price = 0.0;
00425 $attributes =& $productContentObject->contentObjectAttributes();
00426 foreach ( $attributes as $attribute )
00427 {
00428 $dataType = $attribute->dataType();
00429 if ( eZShopFunctions::isProductDatatype( $dataType->isA() ) )
00430 {
00431 $priceObj =& $attribute->content();
00432 $price += $priceObj->attribute( 'price' );
00433 break;
00434 }
00435 }
00436 if ( !is_object( $priceObj ) )
00437 break;
00438
00439 $currency =& $priceObj->attribute( 'currency' );
00440 $optionsPrice = $item->calculatePriceWithOptions( $currency );
00441
00442 $price += $optionsPrice;
00443 $item->setAttribute( "price", $price );
00444 if ( $priceObj->attribute( 'is_vat_included' ) )
00445 {
00446 $item->setAttribute( "is_vat_inc", '1' );
00447 }
00448 else
00449 {
00450 $item->setAttribute( "is_vat_inc", '0' );
00451 }
00452 $item->setAttribute( "vat_value", $priceObj->VATPercent( $productContentObject ) );
00453 $item->setAttribute( "discount", $priceObj->attribute( 'discount_percent' ) );
00454 $item->store();
00455
00456 $currencyCode = $priceObj->attribute( 'currency' );
00457 }
00458
00459 $productCollection->setAttribute( 'currency_code', $currencyCode );
00460 $productCollection->store();
00461 $db->commit();
00462
00463
00464 eZShippingManager::updateShippingInfo( $productCollection->attribute( 'id' ) );
00465 }
00466 }
00467
00468
00469
00470
00471
00472
00473 function cleanupExpired( $time )
00474 {
00475 $db =& eZDB::instance();
00476
00477 if ( $db->hasRequiredServerVersion( '4.0', 'mysql' ) )
00478 {
00479
00480
00481 $sql = "DELETE FROM ezbasket, ezproductcollection, ezproductcollection_item, ezproductcollection_item_opt
00482 USING ezsession
00483 JOIN ezbasket
00484 ON ezsession.session_key = ezbasket.session_id
00485 LEFT JOIN ezproductcollection
00486 ON ezbasket.productcollection_id = ezproductcollection.id
00487 LEFT JOIN ezproductcollection_item
00488 ON ezproductcollection.id = ezproductcollection_item.productcollection_id
00489 LEFT JOIN ezproductcollection_item_opt
00490 ON ezproductcollection_item.id = ezproductcollection_item_opt.item_id";
00491 if ( $time !== false )
00492 $sql .= "\nWHERE ezsession.expiration_time < " . (int)$time;
00493 $db->query( $sql );
00494 return;
00495 }
00496
00497
00498 $sql = "SELECT id, productcollection_id
00499 FROM ezbasket, ezsession
00500 WHERE ezbasket.session_id = ezsession.session_key AND
00501 ezsession.expiration_time < " . (int)$time;
00502 $limit = EZ_BASKET_ITEM_LIMIT;
00503
00504 do
00505 {
00506 $rows = $db->arrayQuery( $sql, array( 'offset' => 0, 'limit' => $limit ) );
00507 if ( count( $rows ) == 0 )
00508 break;
00509
00510 $productCollectionIDList = array();
00511 $idList = array();
00512 foreach ( $rows as $row )
00513 {
00514 $idList[] = (int)$row['id'];
00515 $productCollectionIDList[] = (int)$row['productcollection_id'];
00516 }
00517 eZProductCollection::cleanupList( $productCollectionIDList );
00518
00519 $ids = implode( ', ', $idList );
00520 $db->query( "DELETE FROM ezbasket WHERE id IN ( $ids )" );
00521
00522 } while ( true );
00523 }
00524
00525
00526
00527
00528
00529
00530
00531 function cleanup()
00532 {
00533 $db =& eZDB::instance();
00534 $sql = "SELECT productcollection_id FROM ezbasket";
00535 $limit = EZ_BASKET_ITEM_LIMIT;
00536
00537 $db->begin();
00538 do
00539 {
00540 $rows = $db->arrayQuery( $sql, array( 'offset' => 0, 'limit' => $limit ) );
00541
00542 if ( count( $rows ) == 0 )
00543 break;
00544
00545 $productCollectionIDList = array();
00546 foreach ( $rows as $row )
00547 {
00548 $productCollectionIDList[] = (int)$row['productcollection_id'];
00549 }
00550 eZProductCollection::cleanupList( $productCollectionIDList );
00551
00552 $ids = implode( ', ', $productCollectionIDList );
00553 $db->query( "DELETE FROM ezbasket WHERE productcollection_id IN ( $ids )" );
00554 }
00555 while ( true );
00556 $db->commit();
00557 }
00558
00559
00560
00561
00562 function type()
00563 {
00564 $type = false;
00565
00566
00567 $productCollectionItemList = eZProductCollectionItem::fetchList( array( 'productcollection_id' => $this->attribute( 'productcollection_id' ) ),
00568 true,
00569 0,
00570 1 );
00571
00572 if ( is_array( $productCollectionItemList ) && count( $productCollectionItemList ) === 1 )
00573 {
00574 $product =& $productCollectionItemList[0]->attribute( 'contentobject' );
00575 if ( is_object( $product ) )
00576 {
00577 include_once( 'kernel/shop/classes/ezshopfunctions.php' );
00578 $type = eZShopFunctions::productTypeByObject( $product );
00579 }
00580 }
00581
00582 return $type;
00583 }
00584
00585 function canAddProduct( $contentObject )
00586 {
00587 include_once( 'kernel/shop/classes/ezshopfunctions.php' );
00588 include_once( 'kernel/shop/errors.php' );
00589
00590 $error = EZ_ERROR_SHOP_OK;
00591
00592 $productType = eZShopFunctions::productTypeByObject( $contentObject );
00593 if ( $productType === false )
00594 {
00595 $error = EZ_ERROR_SHOP_NOT_A_PRODUCT;
00596 }
00597 else
00598 {
00599 if ( !eZShopFunctions::isSimplePriceProductType( $productType ) )
00600 $error = eZShopFunctions::isPreferredCurrencyValid();
00601
00602 if ( $error === EZ_ERROR_SHOP_OK )
00603 {
00604 $basketType = $this->type();
00605 if ( $basketType !== false && $basketType !== $productType )
00606 $error = EZ_ERROR_SHOP_BASKET_INCOMPATIBLE_PRODUCT_TYPE;
00607 }
00608 }
00609
00610 return $error;
00611 }
00612
00613 function &productCollection()
00614 {
00615 $productCollection = eZProductCollection::fetch( $this->attribute( 'productcollection_id' ) );
00616 return $productCollection;
00617 }
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628 function cleanupCurrentBasket( $useSetting = true )
00629 {
00630 $ini =& eZINI::instance();
00631 $removeBasket = true;
00632 if ( $useSetting )
00633 $removeBasket = $ini->hasVariable( 'ShopSettings', 'ClearBasketOnLogout' ) ? $ini->variable( 'ShopSettings', 'ClearBasketOnLogout' ) == 'enabled' : false;
00634
00635 if ( $removeBasket )
00636 {
00637 $basket =& eZBasket::currentBasket();
00638 if ( !is_object( $basket ) )
00639 return false;
00640 $db =& eZDB::instance();
00641 $db->begin();
00642 $productCollectionID = $basket->attribute( 'productcollection_id' );
00643 eZProductCollection::cleanupList( array( $productCollectionID ) );
00644 $basket->remove();
00645 $db->commit();
00646 }
00647
00648 return true;
00649 }
00650 }
00651
00652 ?>