OpenCart - Пишем модуль файлов скачивания со страницы производителя

Доброго времени суток!

В одном из наших проектов клиент попросил добавить возможность загружать различные документы (сертификаты, лицензии и так далее), привязывая их к странице производителя и дать возможность скачивать их всем посетителям сайта.

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

Таким образом, текущее решение не устравивает. Поиск в интернете также не принес ничего дельного, поэтому расчехляем исходный код OpenCart и пишем свой модуль.

Для нетерпеливых - репозиторий с готовым кодом.

Что получилость в итоге.

Административная часть

1.jpg

Публичная часть

2.jpg


В этом примере используется чистая версия OpenCart 2.3.0.2

Подготовка

Для начала подготовим нашу базу данных.

Для нашей задачи нужно будет хранить несколько файлов для каждого производителя, то есть связь будет Многие-ко-многим. Создадим в базе данных новую таблицу с именем manufacturer_to_download, где будут храниться связи загруженных файлов и производителей.

create table manufacturer_to_download (
    manufacturer_id INTEGER,
    download_id INTEGER
)

Теперь напишем административную часть нашего модуля.

OpenCart не сложен по своей структуре и реализует обычный паттерн MVC, но с добавлением L (language - язык) для реализации мультиязычности. Каждый модуль разделен на несколько файлов - модель, контроллер, шаблон и языковые файлы с переводами для соответствующего языка.

Будем придерживаться этих правил и создавать всё как положено.

Начнем с модели - нужно получать доступные файлы для скачивания при получении производителя. Добавим нужный функционал.

Для этого изменим несколько строк в файле admin/model/catalog/manufacturer.php

admin / model / catalog / manufacturer.php

<?php
class ModelCatalogManufacturer extends Model {
    public function addManufacturer($data) {
        /***/

        if (isset($data['download'])) {
            foreach ($data['download'] as $download_id) {
                $this->db->query("INSERT INTO " . DB_PREFIX . "manufacturer_to_download SET product_id = '" . (int)$manufacturer_id . "', download_id = '" . (int)$download_id . "'");
            }
        }

        $this->cache->delete('manufacturer');
        return $manufacturer_id;
    }

    public function editManufacturer($manufacturer_id, $data) {

       /***/

        $this->db->query("DELETE FROM " . DB_PREFIX . "manufacturer_to_download WHERE manufacturer_id = '" . (int)$manufacturer_id . "'");

        if (isset($data['download'])) {
            foreach ($data['download'] as $download_id) {
                $this->db->query("INSERT INTO " . DB_PREFIX . "manufacturer_to_download SET manufacturer_id = '" . (int)$manufacturer_id . "', download_id = '" . (int)$download_id . "'");
            }
        }

        $this->cache->delete('manufacturer');
    }

    public function deleteManufacturer($manufacturer_id) {
        /***/

        $this->db->query("DELETE FROM " . DB_PREFIX . "manufacturer_to_download WHERE manufacturer_id = '" . (int)$manufacturer_id . "'");

        $this->cache->delete('manufacturer');
    }

    public function getManufacturerDownloads($id) {
        $download_data = array();

        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "manufacturer_to_download WHERE manufacturer_id = '" . (int)$id . "'");

        foreach ($query->rows as $result) {
            $download_data[] = $result['download_id'];
        }

        return $download_data;
    }
}
admin / controller / catalog / manufacturer.php

$data['button_edit'] = $this->language->get('button_edit');
$data['button_delete'] = $this->language->get('button_delete');

+       $data['help_download'] = $this->language->get('help_download');
+       $data['entry_download'] = $this->language->get('entry_download');
+
        if (isset($this->error['warning'])) {
            $data['error_warning'] = $this->error['warning'];
        } else {
admin / controller / catalog / manufacturer.php

        $data['button_save'] = $this->language->get('button_save');
        $data['button_cancel'] = $this->language->get('button_cancel');

+        $data['help_download'] = $this->language->get('help_download');
+        $data['entry_download'] = $this->language->get('entry_download');
+
        if (isset($this->error['warning'])) {
            $data['error_warning'] = $this->error['warning'];
        } else {

Изменим метод getForm(), а также добавим метод getManufacturerDownloads($id) для получения всех загрузок производителя из БД.

admin / controller / catalog / manufacturer.php

+        // Downloads
+        $this->load->model('catalog/download');
+
+        if (isset($this->request->post['download'])) {
+            $downloads = $this->request->post['download'];
+        } elseif (isset($this->request->get['manufacturer_id'])) {
+            $downloads = $this->model_catalog_manufacturer->getManufacturerDownloads($this->request->get['manufacturer_id']);
+        } else {
+            $downloads = array();
+        }
+
+        $data['downloads'] = array();
+
+        foreach ($downloads as $download_id) {
+            $download_info = $this->model_catalog_download->getDownload($download_id);
+
+            if ($download_info) {
+                $data['downloads'][] = array(
+                    'download_id' => $download_info['download_id'],
+                    'name'        => $download_info['name']
+                );
+            }
+        }
+

        $data['header'] = $this->load->controller('common/header');
        $data['column_left'] = $this->load->controller('common/column_left');
        $data['footer'] = $this->load->controller('common/footer');

        $this->response->setOutput($this->load->view('catalog/manufacturer_form', $data));
    }

+    public function getManufacturerDownloads($id) {
+        $download_data = array();
+
+        $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "manufacturer_to_download WHERE manufacturer_id = '" . (int)$id . "'");
+
+        foreach ($query->rows as $result) {
+            $download_data[] = $result['download_id'];
+        }
+
+
+        return $download_data;
+    }
+

Теперь поправим шаблон. Нам понадобится изменить файл, отвечающий за редактирование определенного производителя - admin / view / template / catalog / manufacturer_form.tpl

admin / view / template / catalog / manufacturer_form.tpl

<h3 class="panel-title"><i class="fa fa-pencil"></i> <?php echo $text_form; ?></h3>
       </div>
       <div class="panel-body">
         <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-manufacturer" class="form-horizontal">
           <div class="form-group required">
             <label class="col-sm-2 control-label" for="input-name"><?php echo $entry_name; ?></label>
             <div class="col-sm-10">
               <input type="text" name="name" value="<?php echo $name; ?>" placeholder="<?php echo $entry_name; ?>" id="input-name" class="form-control" />
               <?php if ($error_name) { ?>
               <div class="text-danger"><?php echo $error_name; ?></div>
               <?php } ?>
             </div>
           </div>
+
+            <div class="form-group">
+                <label class="col-sm-2 control-label" for="input-download">
+                    <span data-toggle="tooltip" title="<?php echo $help_download; ?>"><?php echo $entry_download; ?></span></label>
+                <div class="col-sm-10">
+                    <input type="text" name="download" value="" placeholder="<?php echo $entry_download; ?>" id="input-download" class="form-control" />
+                    <div id="download" class="well well-sm" style="min-height: 150px; overflow: auto;">
+                        <?php foreach ($downloads as $download) { ?>
+                        <div id="download<?php echo $download['download_id']; ?>"><i class="fa fa-minus-circle"></i> <?php echo $download['name']; ?>
+                            <input type="hidden" name="download[]" value="<?php echo $download['download_id']; ?>" />
+                        </div>
+                        <?php } ?>
+                    </div>
+                </div>
+            </div>
+
           <div class="form-group">
             <label class="col-sm-2 control-label"><?php echo $entry_store; ?></label>
             <div class="col-sm-10">

Обязательно внизу страницы добавляем скрипты для обработки загружаемых файлов:

admin / view / template / catalog / manufacturer_form.tpl

+<script>
+// Downloads
+        $('input[name=\'download\']').autocomplete({
+            'source': function(request, response) {
+                $.ajax({
+                    url: 'index.php?route=catalog/download/autocomplete&token=<?php echo $token; ?>&filter_name=' +  encodeURIComponent(request),
+                    dataType: 'json',
+                    success: function(json) {
+                        response($.map(json, function(item) {
+                            return {
+                                label: item['name'],
+                                value: item['download_id']
+                            }
+                        }));
+                    }
+                });
+            },
+            'select': function(item) {
+                $('input[name=\'download\']').val('');
+                $('#download' + item['value']).remove();
+                $('#download').append('<div id="download' + item['value'] + '"><i class="fa fa-minus-circle"></i> ' + item['label'] + '<input type="hidden" name="download[]" value="' + item['value'] + '" /></div>');
+            }
+        });
+
+        $('#download').delegate('.fa-minus-circle', 'click', function() {
+            $(this).parent().remove();
+        });
+</script>

Теперь пришел черёд локализовать изменения. Сделаем в первую очередь для русского языка. Откроем файл admin / language / ru-ru / catalog / manufacturer.php и внесем необходимые правки:

admin / language / ru-ru / catalog / manufacturer.php

+  $_['entry_download']    = 'Файлы для скачивания';
+  $_['help_download']     = '(Автозаполнение)';

Теперь откроем административную часть и перейдем в раздел Производители, предварительно загрузив несколько файлов через Каталог - Загрузки.

1.jpg

Отлично!

Перейдем к публичной части сайта. продолжение следует...