Source of file Product.php
Size: 8,919 Bytes - Last Modified: 2021-12-23T10:47:54+00:00
/var/www/docs.ssmods.com/process/src/code/product/Product.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 | <?php /** * Represents a Product, which is a type of a {@link Page}. Products are managed in a seperate * admin area {@link ShopAdmin}. A product can have {@link Variation}s, in fact if a Product * has attributes (e.g Size, Color) then it must have Variations. Products are Versioned so that * when a Product is added to an Order, then subsequently changed, the Order can get the correct * details about the Product. */ class Product extends Page { /** * Flag for denoting if this is the first time this Product is being written. * * @var Boolean */ protected $firstWrite = false; /** * DB fields for Product. * * @var Array */ private static $db = array( 'Price' => 'Decimal(19,8)', 'Currency' => 'Varchar(3)' ); /** * Actual price in base currency, can decorate to apply discounts etc. * * @return Price */ public function Amount() { // TODO: Multi currency $shopConfig = ShopConfig::current_shop_config(); $amount = Price::create(); $amount->setAmount($this->Price); $amount->setCurrency($shopConfig->BaseCurrency); $amount->setSymbol($shopConfig->BaseCurrencySymbol); //Transform amount for applying discounts etc. $this->extend('updateAmount', $amount); return $amount; } /** * Display price, can decorate for multiple currency etc. * * @return Price */ public function Price() { $amount = $this->Amount(); //Transform price here for display in different currencies etc. $this->extend('updatePrice', $amount); return $amount; } /** * Has many relations for Product. * * @var Array */ private static $has_many = array( 'Attributes' => 'Attribute', 'Options' => 'Option', 'Variations' => 'Variation' ); /** * Defaults for Product * * @var Array */ private static $defaults = array( 'ParentID' => -1 ); /** * Summary fields for displaying Products in the CMS * * @var Array */ private static $summary_fields = array( 'Amount.Nice' => 'Price', 'Title' => 'Title' ); private static $searchable_fields = array( 'Title' => array( 'field' => 'TextField', 'filter' => 'PartialMatchFilter', 'title' => 'Name' ) ); /** * Set firstWrite flag if this is the first time this Product is written. * * @see SiteTree::onBeforeWrite() * @see Product::onAfterWrite() */ public function onBeforeWrite() { parent::onBeforeWrite(); if (!$this->ID) $this->firstWrite = true; //Save in base currency $shopConfig = ShopConfig::current_shop_config(); $this->Currency = $shopConfig->BaseCurrency; } /** * Unpublish products if they get deleted, such as in product admin area * * @see SiteTree::onAfterDelete() */ public function onAfterDelete() { parent::onAfterDelete(); if ($this->isPublished()) { $this->doUnpublish(); } } /** * Set some CMS fields for managing Products * * @see Page::getCMSFields() * @return FieldList */ public function getCMSFields() { $shopConfig = ShopConfig::current_shop_config(); $fields = parent::getCMSFields(); //Product fields $fields->addFieldToTab('Root.Main', new PriceField('Price'), 'Content'); //Replace URL Segment field if ($this->ParentID == -1) { $urlsegment = new SiteTreeURLSegmentField("URLSegment", 'URLSegment'); $baseLink = Controller::join_links(Director::absoluteBaseURL(), 'product/'); $url = (strlen($baseLink) > 36) ? "..." .substr($baseLink, -32) : $baseLink; $urlsegment->setURLPrefix($url); $fields->replaceField('URLSegment', $urlsegment); } if ($this->isInDB()) { //Product attributes $listField = new GridField( 'Attributes', 'Attributes', $this->Attributes(), GridFieldConfig_BasicSortable::create() ); $fields->addFieldToTab('Root.Attributes', $listField); //Product variations $attributes = $this->Attributes(); if ($attributes && $attributes->exists()) { //Remove the stock level field if there are variations, each variation has a stock field $fields->removeByName('Stock'); $variationFieldList = array(); foreach ($attributes as $attribute) { $variationFieldList['AttributeValue_'.$attribute->ID] = $attribute->Title; } $variationFieldList = array_merge($variationFieldList, singleton('Variation')->summaryFields()); $config = GridFieldConfig_HasManyRelationEditor::create(); $dataColumns = $config->getComponentByType('GridFieldDataColumns'); $dataColumns->setDisplayFields($variationFieldList); $listField = new GridField( 'Variations', 'Variations', $this->Variations(), $config ); $fields->addFieldToTab('Root.Variations', $listField); } } //Ability to edit fields added to CMS here $this->extend('updateProductCMSFields', $fields); if ($warning = ShopConfig::base_currency_warning()) { $fields->addFieldToTab('Root.Main', new LiteralField('BaseCurrencyWarning', '<p class="message warning">'.$warning.'</p>' ), 'Title'); } return $fields; } /** * Get the URL for this Product, products that are not part of the SiteTree are * displayed by the {@link Product_Controller}. * * @see SiteTree::Link() * @see Product_Controller::show() * @return String */ public function Link($action = null) { if ($this->ParentID > -1) { return parent::Link($action); } return Controller::join_links(Director::baseURL() . 'product/', $this->RelativeLink($action)); } /** * A product is required to be added to a cart with a variation if it has attributes. * A product with attributes needs to have some enabled {@link Variation}s * * @return Boolean */ public function requiresVariation() { $attributes = $this->Attributes(); $this->extend('updaterequiresVariation', $attributes); return $attributes && $attributes->exists(); } /** * Get options for an Attribute of this Product. * * @param Int $attributeID * @return ArrayList */ public function getOptionsForAttribute($attributeID) { $options = new ArrayList(); $variations = $this->Variations(); if ($variations && $variations->exists()) foreach ($variations as $variation) { if ($variation->isEnabled()) { $option = $variation->getOptionForAttribute($attributeID); if ($option) $options->push($option); } } $options = $options->sort('SortOrder'); return $options; } /** * Validate the Product before it is saved in {@link ShopAdmin}. * * @see DataObject::validate() * @return ValidationResult */ public function validate() { $result = new ValidationResult(); //If this is being published, check that enabled variations exist if they are required $request = Controller::curr()->getRequest(); $publishing = ($request && $request->getVar('action_publish')) ? true : false; if ($publishing && $this->requiresVariation()) { $variations = $this->Variations(); if (!in_array('Enabled', $variations->map('ID', 'Status')->toArray())) { $result->error( 'Cannot publish product when no variations are enabled. Please enable some product variations and try again.', 'VariationsDisabledError' ); } } return $result; } } /** * Displays a product, add to cart form, gets options and variation price for a {@link Product} * via AJAX. * * @author Frank Mullenger <frankmullenger@gmail.com> * @copyright Copyright (c) 2011, Frank Mullenger * @package swipestripe * @subpackage product */ class Product_Controller extends Page_Controller { /** * Allowed actions for this controller * * @var Array */ private static $allowed_actions = array( 'ProductForm' ); /** * Include some CSS and set the dataRecord to the current Product that is being viewed. * * @see Page_Controller::init() */ public function init() { parent::init(); Requirements::css('swipestripe/css/Shop.css'); //Get current product page for products that are not part of the site tree //and do not have a ParentID set, they are accessed via this controller using //Director rules if ($this->dataRecord->ID == -1) { $params = $this->getURLParams(); if ($urlSegment = Convert::raw2sql($params['ID'])) { $product = Product::get() ->where("\"URLSegment\" = '$urlSegment'") ->limit(1) ->first(); if ($product && $product->exists()) { $this->dataRecord = $product; $this->failover = $this->dataRecord; $this->customise(array( 'Product' => $this->data() )); } } } $this->extend('onInit'); } /** * Legacy function allowing access to product data via $Product variable in templates */ public function Product() { return $this->data(); } public function ProductForm($quantity = null, $redirectURL = null) { return ProductForm::create( $this, 'ProductForm', $quantity, $redirectURL )->disableSecurityToken(); } } |