Оформление заказа в один шаг – tpl шаблонизатор

Материал из Umicms
Перейти к:навигация, поиск

Актуально для 2.11

В данной статье будет описан принцип создания формы оформления заказа за один шаг, т.е. все необходимые данные, регистрационные данные покупателя, способ доставки, способ оплаты и т.д. представлены на одной страницы. Для использования информации в данной статье версия вашей системы должна быть не ниже 2.8.4.3, иначе код не будет нормально функционировать при наличии в модуле Интернет-магазин способа доставки Курьером, и способа оплаты "Курьером при получении".

Нам понадобятся дополнительные php-методы для реализации данной задачи, которые необходимо добавить внутри абстрактного класса файла classes/modules/emarket/__custom.php, сами методы следующие:

public function deliveryAddressesListCustom($template = 'onestep') {
	$order = $this->getBasketOrder(false);
	list($tpl_block, $tpl_item) = def_module::loadTemplates(
		"emarket/delivery/{$template}.tpl",
		"delivery_address_block",
		"delivery_address_item"
	);

	$customer  = customer::get();
	$addresses = $customer->delivery_addresses;
	$items_arr = array();
	$currentDeliveryId = $order->getValue('delivery_address');

	$collection = umiObjectsCollection::getInstance();

	if (is_array($addresses)) foreach($addresses as $address) {
		$addressObject = $collection->getObject($address);

		$item_arr = array(
			'attribute:id'		=> $address,
			'attribute:name'	=> $addressObject->name
		);

		if ($address == $currentDeliveryId) $item_arr['attribute:active'] = 'active';

		$items_arr[] = def_module::parseTemplate($tpl_item, $item_arr, false, $address);
	}

	$types  = umiObjectTypesCollection::getInstance();
	$typeId = $types->getBaseType("emarket", "delivery_address");

	if ($tpl_block) {
		return def_module::parseTemplate($tpl_block, array('items' => $items_arr, 'type_id' => $typeId));
	}
}

public function deliveryListCustom($template = 'onestep') {
	$order = $this->getBasketOrder(false);
	list($tpl_block, $tpl_item_free, $tpl_item_priced) = def_module::loadTemplates(
		"emarket/delivery/{$template}.tpl",
		'delivery_block',
		'delivery_item_free',
		'delivery_item_priced'
	);

	if (!isset($_SESSION['emarket'])) $_SESSION['emarket'] = array();
	if (!isset($_SESSION['emarket']['delivery'])) $_SESSION['emarket']['delivery'] = array();

	$deliveryIds = delivery::getList();
	$items_arr = array();
	$currentDeliveryId = $order->getValue('delivery_id');

	foreach($deliveryIds as $delivery) {
		$delivery = delivery::get($delivery);
		if ($delivery->validate($order) == false) {
			continue;
		}

		$deliveryObject = $delivery->getObject();
		$deliveryPrice  = $delivery->getDeliveryPrice($order);
		$_SESSION['emarket']['delivery'][$delivery->id] = (float)$deliveryPrice;

		$item_arr = array(
			'attribute:id'		=> $deliveryObject->id,
			'attribute:name'	=> $deliveryObject->name,
			'attribute:price'	=> $deliveryPrice.'',
			'xlink:href'		=> $deliveryObject->xlink
		);

		if ($delivery->id == $currentDeliveryId) $item_arr['attribute:active'] = 'active';

		$tpl_item = $deliveryPrice ? $tpl_item_priced : $tpl_item_free;
		$items_arr[] = def_module::parseTemplate($tpl_item, $item_arr, false, $deliveryObject->id);
	}

	if ($tpl_block) {
		return def_module::parseTemplate($tpl_block, array('items' => $items_arr));
	} else {
		return array('items' => array('nodes:item'	=> $items_arr));
	}

}

public function paymentsListCustom($template = 'onestep') {
	$order = $this->getBasketOrder(false);
	list($tpl_block, $tpl_item) = def_module::loadTemplates("emarket/payment/{$template}.tpl", 'payment_block', 'payment_item');

	$payments = payment::getList();
	$items = array();
	$currentPaymentId = $order->getValue('payment_id');

	foreach($payments as $paymentId) {
		$payment = payment::get($paymentId, $order);
		if($payment->validate($order) == false) {
			continue;
		}
		$paymentObject = $payment->getObject();
		$paymentTypeId = $paymentObject->getValue('payment_type_id');
		$paymentTypeName = umiObjectsCollection::getInstance()->getObject($paymentTypeId)->getValue('class_name');

		if($paymentTypeName == 'social') {
			continue;
		}

		$item = array(
			'attribute:id'			=> $paymentObject->id,
			'attribute:name'		=> $paymentObject->name,
			'attribute:type-name'	=> $paymentTypeName,
			'xlink:href'			=> $paymentObject->xlink
		);

		if($paymentId == $currentPaymentId) {
			$item['attribute:active'] = 'active';
		}

		$items[] = def_module::parseTemplate($tpl_item, $item, false, $paymentObject->id);
	}

	if($tpl_block && !def_module::isXSLTResultMode()) {
		return def_module::parseTemplate($tpl_block, array('items' => $items));
	} else {
		return array('items' => array('nodes:item'	=> $items));
	}
}

public function personalInfoCustom($template = 'onestep') {
	if (!permissionsCollection::getInstance()->isAuth()){
		$customerId = customer::get()->id;
		$cmsController = cmsController::getInstance();
		$data = $cmsController->getModule('data');

		return $data->getEditForm($customerId, $template);
	} else return '';
}

public function saveInfoCustom(){
	$order = $this->getBasketOrder(false);

	//сохранение регистрационных данных
	$cmsController = cmsController::getInstance();
	$data = $cmsController->getModule('data');
	$data->saveEditedObject(customer::get()->id, false, true);

	//сохранение адреса доставки
	$addressId = getRequest('delivery-address');
	if ($addressId == 'new') {
		$collection = umiObjectsCollection::getInstance();
		$types      = umiObjectTypesCollection::getInstance();
		$typeId     = $types->getBaseType("emarket", "delivery_address");
		$customer   = customer::get();
		$addressId  = $collection->addObject("Address for customer #".$customer->id, $typeId);
		$dataModule = $cmsController->getModule("data");
		if ($dataModule) {
			if (!$dataModule->saveEditedObject($addressId, true, true)) {
				$dataModule->saveEditedObjectWithIgnorePermissions($addressId, true, true); // начиная с версии 2.9.5
			}
		}
		$customer->delivery_addresses = array_merge( $customer->delivery_addresses, array($addressId) );
	}
	$order->delivery_address = $addressId;

	//сохранение способа доставки
	$deliveryId = getRequest('delivery-id');
	if ($deliveryId){
		$delivery = delivery::get($deliveryId);
		$deliveryPrice = (float) $delivery->getDeliveryPrice($order);
		$order->setValue('delivery_id', $deliveryId);
		$order->setValue('delivery_price', $deliveryPrice);
	}

	//сохранение способа оплаты и редирект на итоговую страницу
	$order->setValue('payment_id', getRequest('payment-id'));

	$order->refresh();

	$paymentId = getRequest('payment-id');
	if (!$paymentId) {
		$this->errorNewMessage(getLabel('error-emarket-choose-payment'));
		$this->errorPanic();
	}
	$payment = payment::get($paymentId, $order);

	if ($payment instanceof payment) {
		$paymentName = $payment->getCodeName();
		$url = "{$this->pre_lang}/".cmsController::getInstance()->getUrlPrefix()."emarket/purchase/payment/{$paymentName}/";
	} else {
		$url = "{$this->pre_lang}/".cmsController::getInstance()->getUrlPrefix()."emarket/cart/";
	}
	$this->redirect($url);
}

также в папку classes/modules/emarket/ необходимо добавить файл permissions.custom.php следующего содержания:

<?php
$permissions = array('purchasing' => array('deliveryListCustom', 'deliveryAddressesListCustom', 'paymentsListCustom', 'personalInfoCustom', 'saveInfoCustom'));
?>

Необходимо создать шаблон tpls/emarket/delivery/onestep.tpl:

<?php
$FORMS = Array();

$FORMS['delivery_block'] = <<<END
	<h3 class="dost">Выберите подходящий вам способ доставки:</h3>
	<ul>
		%items%
	</ul>
END;

$FORMS['delivery_item_free'] = <<<END
	<li><input type="radio" name="delivery-id" value="%id%" checked="checked" /> %name% - бесплатно</li>
END;

$FORMS['delivery_item_priced'] = <<<END
	<li><input type="radio" name="delivery-id" value="%id%" /> %name% - %price%</li>
END;

$FORMS['delivery_address_block'] = <<<END
	<div class="adrest">
	<h3 class="dost">Выберите подходящий вам адрес доставки:</h3>
		<ul>
			%items%
			<li>
				<input type="radio" name="delivery-address" value="new" /> <b>Новый адрес доставки:</b>
				<table cellspacing="1" cellpadding="1" width="100%" border="0">
					%data getCreateForm(Здесь нужно подставить ид типа данных "Адрес доставки", 'onestep')%
				</table>
			</li>
		</ul>
	</div>
END;

$FORMS['delivery_address_item'] = <<<END
	<li><input type="radio" name="delivery-address" value="%id%" />%index%, %city%, %street%, д. %house%, кв. %flat%</li>
END;

?>

В макросе data getCreateForm(), первый параметр - это id типа данных "Адрес доставки" в модуле "Шаблоны данных", первая вкладка, раздел "Справочники", этот id вы должны для вашей системы определить самостоятельно и подставить в макрос data getCreateForm().

Шаблон tpls/emarket/payment/onestep.tpl:

<?php
$FORMS = Array();

$FORMS['payment_block'] = <<<END
	Выберите подходящий вам способ оплаты:
	<ul>
		%items%
	</ul>
END;

$FORMS['payment_item'] = <<<END
	<li><input type="radio" name="payment-id" value="%id%" /> %name%</li>
END;

?>

Шаблон tpls/data/reflection/onestep.tpl:

<?php

$FORMS = Array();

$FORMS['reflection_block'] = <<<END
%groups%
END;

$FORMS['reflection_group'] = <<<END
	<tr>
		<td colspan="2">
			<br/><br /><b>%title%</b><br /><br />
		</td>
	</tr>
	%fields%
END;

$FORMS['reflection_field_string'] = <<<END
	<tr>
		<td>
			%title%%required_asteriks%:
		</td>

		<td>
			<input type="text" name="%input_name%" value="%value%" class="textinputs" />
		</td>
	</tr>
END;

$FORMS['reflection_field_text'] = <<<END
	<tr>
		<td>
			%title%%required_asteriks%:
		</td>
		<td>
			<textarea name="%input_name%" class="textinputs">%value%</textarea>
		</td>
	</tr>
END;

$FORMS['reflection_field_int'] = <<<END
	<tr>
		<td>
			%title%%required_asteriks%:
		</td>

		<td>
			<input type="text" name="%input_name%" value="%value%" class="textinputs" />
		</td>
	</tr>
END;

$FORMS['reflection_field_relation'] = <<<END
	<tr>
		<td>
			%title%%required_asteriks%:
		</td>

		<td>
			<select name="%input_name%" style="width: 205px" class="textinputs">
				<option />
				%options%
			</select>
		</td>
	</tr>

END;

$FORMS['reflection_field_relation_option'] = <<<END
	<option value="%id%">%name%</option>
END;

$FORMS['reflection_field_relation_option_a'] = <<<END
	<option value="%id%" selected="selected">%name%</option>
END;

?>

В шаблоне tpls/emarket/default.tpl, в блоке order_block, форма должна быть примерно следующая:

<form action="%pre_lang%/emarket/saveInfoCustom/">
	%emarket deliveryListCustom('onestep')%
	%emarket deliveryAddressesListCustom('onestep')%
	<table cellspacing="1" cellpadding="1" width="100%" border="0">
	</table>
	<br/>
	%emarket paymentsListCustom('onestep')%
	<br/>
	<table cellspacing="1" cellpadding="1" width="100%" border="0">
		%emarket personalInfoCustom('onestep')%
	</table>
	<br/>
	<input type="submit" value="Оформить заказ" />
</form>