Webylon 3.2 API Docs
  • Package
  • Class
  • Tree
  • Deprecated
  • Download
Version: current
  • 3.2
  • 3.1

Packages

  • 1c
    • exchange
      • catalog
  • auth
  • Booking
  • building
    • company
  • cart
    • shipping
    • steppedcheckout
  • Catalog
    • monument
  • cms
    • assets
    • batchaction
    • batchactions
    • bulkloading
    • comments
    • content
    • core
    • export
    • newsletter
    • publishers
    • reports
    • security
    • tasks
  • Dashboard
  • DataObjectManager
  • event
  • faq
  • forms
    • actions
    • core
    • fields-basic
    • fields-dataless
    • fields-datetime
    • fields-files
    • fields-formatted
    • fields-formattedinput
    • fields-relational
    • fields-structural
    • transformations
    • validators
  • googlesitemaps
  • guestbook
  • installer
  • newsletter
  • None
  • photo
    • gallery
  • PHP
  • polls
  • recaptcha
  • sapphire
    • api
    • bulkloading
    • control
    • core
    • cron
    • dev
    • email
    • fields-formattedinput
    • filesystem
    • formatters
    • forms
    • i18n
    • integration
    • misc
    • model
    • parsers
    • search
    • security
    • tasks
    • testing
    • tools
    • validation
    • view
    • widgets
  • seo
    • open
      • graph
  • sfDateTimePlugin
  • spamprotection
  • stealth
    • captha
  • subsites
  • userform
    • pagetypes
  • userforms
  • webylon
  • widgets

Classes

  • Cart
  • CartOrderButton
  • CartPage
  • CartSiteConfig
  • CartTableListField
  • CheckoutPage
  • ExtendGroupDiscount
  • ExtendMemberCart
  • ExtendPageCart
  • ExtendPageSpecialCatalog
  • ExtendProductSpecialCatalog
  • ExtendProfilePageOrder
  • Order
  • OrderAdmin
  • OrderExporter
  • OrderItem
  • OrderItemField
  • SpecialCatalog
  • TextLiteralField
  1 <?php
  2 
  3 /**
  4  * Страница управления заказом
  5  *
  6  * @package cart
  7  * @author inxo, dvp
  8  */
  9 class CheckoutPage extends Page {
 10 
 11     static $icon = "cart/img/cart";
 12     static $allowed_children = 'none';
 13 
 14     static $db = array(
 15         'PurchaseComplete' => 'HTMLText',
 16         'ChequeMessage' => 'HTMLText'
 17     );
 18 
 19     static $has_one = array(
 20         'TermsPage' => 'Page'
 21     );
 22 
 23     static $defaults = array(
 24         'AutoChild' => 0,
 25         "DevEditType" => "Fixed",
 26         'ShowInSiteMap' => 0,
 27         'ShowInSearch' => 0,
 28         'ShowInMenu' => 0,
 29         'URLSegment' => 'checkout',
 30     );
 31 
 32     static $use_steps = false;
 33 
 34     /**
 35      * Возвращает ссылку на страницу заказа
 36      *
 37      * @param string $action - действие со страницей
 38      * @return string ссылка на страницу
 39      */
 40     static function find_link($action = '') {
 41         if (!$page = DataObject::get_one('CheckoutPage')) {
 42             user_error('Создайте страницу заказа', E_USER_ERROR);
 43         }
 44 
 45         return $page->Link($action);
 46     }
 47 
 48     /**
 49      * Автоматическая генерация страницы заказа
 50      * TODO локализация!!!
 51      */
 52     function requireDefaultRecords() {
 53         parent::requireDefaultRecords();
 54 
 55         if (!$page = DataObject::get_one('CheckoutPage')) {
 56             $page = new CheckoutPage();
 57             $page->writeToStage('Stage');
 58             $page->publish('Stage', 'Live');
 59 
 60             if (method_exists('DB', 'alteration_message'))
 61                 DB::alteration_message('Checkout page created', 'created');
 62         }
 63 
 64         if ($page->TermsPageID == 0 && $termsPage = DataObject::get_one('Page', "\"URLSegment\" = 'terms'")) {
 65             $page->TermsPageID = $termsPage->ID;
 66             $page->writeToStage('Stage');
 67             $page->publish('Stage', 'Live');
 68 
 69             if (method_exists('DB', 'alteration_message'))
 70                 DB::alteration_message("Page '{$termsPage->Title}' linked to the Checkout page '{$page->Title}'", 'changed');
 71         }
 72     }
 73 
 74     function canCreate() {
 75         return (DataObject::get_one('CheckoutPage')) ? false : true;
 76     }
 77     
 78     function populateDefaults() {
 79         parent::populateDefaults();
 80         
 81         $this->Title = $this->i18n_singular_name();
 82         $this->PurchaseComplete = _t('CheckoutPage.default_PurchaseComplete', 'Thank You for purchase');
 83         $this->ChequeMessage = _t('CheckoutPage.default_ChequeMessage', 'Payment accepted via Cheque. Please note : products will not be shipped until payment has been received');
 84         $this->URLSegment = 'checkout';
 85     }
 86 
 87     function getCMSFields() {
 88         SiteTree::disableCMSFieldsExtensions();
 89         $fields = parent::getCMSFields();
 90         SiteTree::enableCMSFieldsExtensions();
 91 
 92         $fields->addFieldToTab('Root.Content.Main', new TreeDropdownField('TermsPageID', $this->fieldLabel('TermsPage'), 'SiteTree'));
 93 
 94         $fields->addFieldToTab('Root.Content', new Tab("Messages", _t('CheckoutPage.tab_Messages', 'Message Config')), 'Metadata');
 95         $fields->addFieldsToTab('Root.Content.Messages', array(
 96             new HtmlEditorField('PurchaseComplete', $this->fieldLabel('PurchaseComplete'), 20),
 97             new HtmlEditorField('ChequeMessage', $this->fieldLabel('ChequeMessage'), 20)
 98         ));
 99 
100         $this->extend('updateCMSFields', $fields);
101 
102         return $fields;
103     }
104 
105     /**
106      * Проверяет достаточна ли сумма заказа для оформления покупки
107      *
108      * @param int $price - сумма заказа [сумма в корзине]
109      *
110      * @return boolean
111      */
112     function CanCheckout($price=null) {
113         return Cart::current_order()->CanCheckout($price);
114     }
115 
116     /**
117      * Возвращает минимальную сумму для заказа
118      *
119      * @param bool $real - возвращать число, а не объект CatalogPrice
120      *
121      * @return int
122      */
123     function MinTotalPrice($real=false) {
124         return Cart::current_order()->MinTotalPrice($real);
125     }
126     
127     /**
128      * Проверяет, есть ли в корзине товары
129      *
130      * @return int
131      */
132     function HasItems() {
133         return Cart::has_items();
134     }
135     
136     /**
137      * Возвращает текущий заказ
138      *
139      * @return Order
140      */
141     function Cart() {
142         return Cart::current_order();
143     }
144 }
145 
146 class CheckoutPage_Controller extends Page_Controller {
147 
148     static $allowed_actions = array('order', 'printorder', 'OrderForm');
149 
150     /**
151      * Хранит сообщение о ошибках валидации заказа для шаблона
152      * @var string
153      */
154     private $orderError = '';
155 
156     function isEmptyContent() {
157         return false;
158     }
159 
160     /**
161      * Обертка для OrderForm для шаблона
162      * 
163      * @return Form|NULL
164      */
165     function Form() {
166         if (!$form = $this->OrderForm()) return false;
167         
168         if($member = Member::currentUser()){
169             $form->loadDataFrom($member);
170         }
171         $form->loadDataFrom(Cart::get_info());
172         
173         return $form;
174     }
175     
176     /**
177      * Форма оформления заказа без шагов
178      * 
179      * Форма годится только для простого случая (без авторизации, доставки или оплаты)
180      * и не используется если настроены шаги
181      * 
182      * Форму можно изменить с помощью расширения подключенного к CheckoutPage_Controller
183      * В расширении можно определить метод:
184      * updateOrderForm(Form &$form) - для изменения формы в целом.
185      *
186      * Либо с помощью расширений подключенных к Order
187      * @see Order::getFrontendFields()
188      * 
189      * @return <type>
190      */
191     function OrderForm() {
192         if (CheckoutPage::$use_steps) return false;
193         $siteConfig = SiteConfig::current_site_config();
194         if ($siteConfig->CartRegisterRequire && !Member::currentUser()) {
195             return $this->redirect('/Security/login?BackURL=' . $this->Link());
196         }
197         
198         $fields = singleton('Order')->getFrontendFields();
199         if ($this->TermsPageID && $terms = $this->TermsPage()) {
200             $fields->push(new CheckboxField('Agree', sprintf(_t('OrderForm.Agree', 'I agree with <a href="%s">terms and conditions</a>'), $terms->Link())));
201         }
202         
203         $required = $this->getOrderRequired();
204         if ($siteConfig->hasMethod('SiteAgreementField') && ($rulesField = $siteConfig->SiteAgreementField())) {
205             $required[] = $rulesField->Name();
206         }
207         $form = new Form(
208             $this,
209             'OrderForm',
210             $fields,
211             new FieldSet(new FormAction("saveorder", _t('OrderForm.SaveOrderButton', "Confirm and Pay"))),
212             new CustomRequiredFields($required)
213         );
214         $form->addExtraClass('OrderForm');
215         
216         $this->extend('updateOrderForm', $form);
217         return $form;
218     }
219     
220     /**
221      * Метод для размещения заказа.
222      *
223      * Вызывается из формы при ее субмите.
224      * Первоначально запоминает данные формы в корзине, после - вызывает метод CheckoutPage->placeOrder() для размещения заказа на сайте.
225      * В случае успешного размещения заказа - показывает страницу с уведомлением.
226      * Использует шаблоны: CheckoutPage_done, CheckoutPage, Page
227      *
228      * @param array $data - данные формы
229      * @param Form $form - форма шага
230      *
231      * @return string
232      */
233     function saveorder($data, $form) {
234         foreach ($form->fields()->saveableFields() as $field) {
235             if ($field->name == 'SecurityID') continue;
236             if ($field->name == 'Agree') continue;
237             $val = 0;
238             if (isset($data[$field->name])) {
239                 $val = $data[$field->name];
240             }
241             Cart::set_info($field->name, $val);
242         }
243 
244         if (!$order = $this->placeOrder()) {
245             $form->sessionMessage($this->getOrderError(), 'bad');
246             Director::redirectBack();
247             return false;
248         }
249         
250         //by menedem для платежей
251         if (class_exists('PaymentMethod') && Order::$use_payments) {
252             $paymentResult = false;
253             if ($paymentMethodID = Cart::get_info('PaymentMethod')) {
254                 $method = DataObject::get_by_id('PaymentMethod', $paymentMethodID);
255                 if ($method) {
256                     $paymentResult = $method->makePayment($order);
257                 } else {
258                     user_error("Ошибочный тип платежа!", E_USER_ERROR);
259                 }
260             }
261             
262             // Возможно нужны разные действия при Payment_Success и Payment_Processing
263             if (!Director::redirected_to()) {
264                 $value = false;
265                 if ($paymentResult)
266                     $value = $paymentResult->getValue();
267                 //какое-то кеширование проклятое
268                 $newOrder = DataObject::get_by_id('Order', $order->ID);
269                 $html = $this->renderWith(
270                     array('CheckoutPage_done', 'CheckoutPage', 'Page'),
271                     array('Form' => false, 'Order' => $newOrder, 'PaymentResult' => $value)
272                 );
273             }
274         } else {
275             if (!Director::redirected_to()) {
276                 $html = $this->renderWith(
277                     array('CheckoutPage_done', 'CheckoutPage', 'Page'),
278                     array('Form' => false, 'Order' => $order)
279                 );
280             }
281         }
282         
283         // отправляем письмо с составом заказа после всех оформлений, чтоб в него можно было вложить информацию о способе платежа
284         $order->extend('OnAfterCreateOrder', Member::CurrentUser());
285         return $html;
286     }
287 
288     /**
289      * Размещает заказ в магазине.
290      * Вызывается после прохождения всех шагов оформления заказа.
291      * В случае ошибки ее текст можно получить с помощью getOrderError().
292      * Позволяет использовать расширения:
293      * - OnBeforeOrder(Order &$order) - вызывается до размещения заказа и проверок на валидность
294      * - OnAfterOrder(Order &$order) - вызывается после размещения заказа до отсылки письма
295      *
296      * @param Order $order - предварительный заказ для размещения, по умолчанию - текущая корзина.
297      * @return mixed $order или false если заказ не прошел валидацию
298      */
299     function placeOrder($order = null) {
300         if (!$order) $order = Cart::current_order();
301 
302         $this->extend('OnBeforeOrder', $order);
303 
304         $result = $order->validate();
305         if (!$result->valid()) {
306             $this->orderError = $result->message();
307             return false;
308         }
309 
310         $order->write();
311         $order->createItems(Cart::get_items(), true);
312         $this->extend('OnAfterOrder', $order);  
313 
314         Cart::set_info('ClientNotes', '');
315         Cart::clear();
316 
317         return $order;
318     }
319 
320     /**
321      * Возвращает ошибку при размещении заказа
322      *
323      * @return string
324      */
325     function getOrderError() {
326         return $this->orderError;
327     }
328 
329     /* Page Actions */
330     
331     /**
332      * Показывает информацию о заказе после его оформления
333      *
334      * Заказ определяется через url вида /order/order/204b22a36e328000dbb841cb3ac4d45e по HashLink заказа
335      * Использует шаблон CheckoutPage_order
336      * @TODO дополнительная проверка пользователя по email ? номеру заказа
337      */
338     function order() {
339         if (!$order = Order::get_by_hash($this->getRequest()->param('ID'))) $this->httpError(404, 'Page not found');
340 
341         return $this->render(array(
342             'Form' => false,
343             'Order' => $order,
344         ));
345     }
346     
347     /**
348      * Показывает страницу печати заказа
349      * Использует шаблон CheckoutPage_printorder
350      */
351     function printorder() {
352         return $this->order();
353     }
354 
355     /* Field generators */
356 
357     /**
358      * Список полей для формы контактной информации
359      *
360      * В расширении можно определить метод:
361      * updateContactDetailsFields(FieldSet &$fields) - для изменения списка полей формы
362      *
363      * @return FieldSet
364      */
365     function getContactDetailsFields() {
366         $fields = singleton('Order')->getContactFields();
367         $this->extend('updateContactDetailsFields', $fields);
368         return $fields;
369     }
370 
371     /**
372      * Список полей для формы подтверждения заказа
373      *
374      * В расширении можно определить метод:
375      * updateSummaryFields(FieldSet &$fields) - для изменения списка полей формы
376      *
377      * @return FieldSet
378      */
379     function getSummaryFields() {
380         $fields = singleton('Order')->getSummaryFields();
381 
382         if ($this->TermsPageID && $terms = $this->TermsPage()) {
383             $fields->push(new CheckboxField('Agree', sprintf(_t('OrderForm.Agree', 'I agree with <a href="%s">terms and conditions</a>'), $terms->Link())));
384         }
385 
386         $this->extend('updateSummaryFields', $fields);
387         return $fields;
388     }
389 
390     /**
391      * Список обязательный полей для формы заказа
392      *
393      * В расширении можно определить метод:
394      * updateOrderRequired(array &$fields) - для изменения списка обязательных полей формы
395      *
396      * @return array
397      */
398     function getOrderRequired() {
399         $required = singleton('Order')->getRequredFields();
400 
401         if ($this->TermsPageID && $terms = $this->TermsPage()) {
402             $required[] = 'Agree';
403         }
404 
405         $this->extend('updateOrderRequired', $required);
406         return $required;
407     }
408     
409 }
410 
[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -
Webylon 3.2 API Docs API documentation generated by ApiGen 2.8.0