Ответ на вопрос 1 Подобное поведение сортировки уже на уровне ядра движка давно выполняется для товаров, отмеченных флагом не продаём. То есть такие товары всегда располагаются в конце списка, какой бы способ сортировки не использовался в этот момент на сайте.
Кстати, указанный флаг и связанную с ним функциональность, условно называемую "экспонаты", редко кто использует. И если у вас на сайте такая функциональность тоже отброшена, тогда задача решалась бы простым образом и состояла в том, чтобы связать наличие/отсутствие на складе с немедленной простановкой флага не продаём.
Простановка флага могла бы выполняться менеджером вручную, когда редактирует наличие товара. А можно автоматизировать, возложив контроль на некий метод хелпера шаблона, например checkStockFlag, который с паузой 1Час-секунд выполняет запрос к базе данных на установку соответствующего флаг-поля non_usable согласно состояния складского поля stock (файл-таймер контроллер с помощью метода checkFileTimer - лишь один из способов выполнения периодических действий в многопоточном трафике).
<?php
class TemplateEmulator {
protected $cms;
public function __construct ( & $cms ) {
$this->cms = & $cms;
$this->checkStockFlag();
...
...
}
...
...
private function checkStockFlag () {
$file = dirname(__FILE__) . '/../../../cache/checkStockFlag.FileTimer.tmp';
if ($this->checkFileTimer($file, 60 * 60)) {
$this->cms->db->query(
'UPDATE `products`, ' .
'`products_variants` ' .
'SET `products`.`non_usable` = CASE WHEN `products_variants`.`stock` > 0 ' .
'THEN 0 ' .
'ELSE 1 ' .
'END ' .
'WHERE `products`.`product_id` = `products_variants`.`product_id`'
);
}
}
private function checkFileTimer ( $file, $lifetime ) {
$handle = @ fopen($file, 'rb');
if ($handle !== FALSE) {
@ fclose($handle);
$date = @ filemtime($file);
if ($date === FALSE) return FALSE;
$now = time();
if ($now >= $date && $now <= $date + $lifetime) return FALSE;
}
return @ touch($file);
}
}
?>
Кстати, для вывода кнопки "В корзину" подойдёт следующая шаблонизационная функция, используемая здесь в упрощённом виде.
{if $helper->maybeSale($product)}
В корзину
{else}
Нет в наличии
{/if}
А вот полный вид, который учитывает ситуации, что товар:
- имеется в наличии
- отсутствует, но разрешена продажа под заказ
- отсутствует и запрещена продажа под заказ
- является экспонатом
{$state = $helper->maybeSale($product)}
{if $state === TRUE}
В корзину
{elseif $state}
Под заказ
{elseif $state === FALSE}
Нет в наличии
{else}
Экспонат
{/if}