Opencart 2.0.1.1 bugfix: OC2 extension installer

- Posted in Uncategorized by

Подарок тем пользователям OC2, которые ловят ошибки JSON Error при попытках использовать стандартный установщик расширений в OC2 (при правильно прописанных параметрах в настройках магазина на вкладке FTP).

Ошибок оказалось целых три. Причём не у всех хостеров проявлялось: где-то работает инсталл, где-то нет. Повезло исследовать ситуацию на проблемном хостинге - в результате вылечили опенкартовский инсталлятор расширений.

  • Исправлена ошибка "PHP Warning: Invalid argument supplied for foreach() ... on line 333";
  • Подавление вывода предупреждений "PHP Warning: ftp_mkdir(): Create directory operation failed ... on line 338" (возникает всегда - при попытках создания существующих каталогов, таких как catalog, admin, admin/controller и т.д.);
  • включение пассивного режима FTP для устранения ошибки "PHP Warning: ftp_put(): Illegal PORT command ... on line 345"

Также описано на OpencartJazz: OCJ :: OC2 extension installer bugfix. Там прикреплён изменённый файл, но пока его можно скачать только после регистрации и "покупки" за 0.00. Будет время - починю это неудобство.

Для параноиков: мне даром не нужны ваши регистрации и личная информация. Просто мне удобно обслуживать и обновлять файлы в одном месте. И это место на данный момент -- там.
commit a60015450b6516406dcbf15f5e978b43eeee693f
Author: Ruslan Brest <rb@labtodo.com>
Date:   Thu Dec 25 20:43:39 2014 +0200
    [!] bugfix OC2 extension installer:
    
    - fix "PHP Warning:  Invalid argument supplied for foreach() ... on line 333";
    - prevent "PHP Warning:  ftp_mkdir(): Create directory operation failed ... on line 338"
      (when existing directories created: catalog, admin, admin/controller, etc.);
    - prevent "PHP Warning:  ftp_put(): Illegal PORT command ... on line 345"
diff --git a/public_html/admin/controller/extension/installer.php b/public_html/admin/controller/extension/installer.php
index 55f4517..1755cca 100644
--- a/public_html/admin/controller/extension/installer.php
+++ b/public_html/admin/controller/extension/installer.php
@@ -295,6 +295,10 @@ class ControllerExtensionInstaller extends Controller {
                $login = ftp_login($connection, $this->config->get('config_ftp_username'), $this->config->get('config_ftp_password'));
 
                if ($login) {
+
+                   // Prevent "PHP Warning:  ftp_put(): Illegal PORT command"
+                   ftp_pasv($connection, true);
+
                    if ($this->config->get('config_ftp_root')) {
                        $root = ftp_chdir($connection, $this->config->get('config_ftp_root'));
                    } else {
@@ -330,12 +334,16 @@ class ControllerExtensionInstaller extends Controller {
                                // Basename all the directories because on some servers they don't return the fulll paths.
                                $list_data = array();
                                
-                               foreach ($list as $list) {
-                                   $list_data[] = basename($list);
+                               if (FALSE !== $list) {
+                                   foreach ($list as $list_item) {
+                                       $list_data[] = basename($list_item);
+                                   }
                                }
                                                                
                                if (!in_array(basename($destination), $list_data)) {
-                                   if (!ftp_mkdir($connection, $destination)) {
+                                   // Prevent "PHP Warning:  ftp_mkdir(): Create directory operation failed" when
+                                   // existing directories created
+                                   if (!@ftp_mkdir($connection, $destination)) {
                                        $json['error'] = sprintf($this->language->get('error_ftp_directory'), $destination);
                                    }
                                }

Новая система модулей OCMOD Opencart Modification System

- Posted in Opencart by

Начало появляться описание формата и отличий новой системы расширений OCMOD от использовавшейся ранее разработки: широко известного VQMOD, автором которой является Qphoria.

Суть системы расширений осталась та же самая, но XML форматы VQMOD и OCMOD отличаются, поэтому модули придётся переписывать. OCMOD - упрощённая версия VQMOD. В админке также добавлены удобства для загрузки новых OCMOD-расширений (Extensions / Extension Installer).

Например, основные отличия OCMOD от VQMOD: имеются операторы Replace, Before, After, Regex, Offset, Limit, отсутствуют ignoreif, log.

Отличается и работа offset.

Модули могут состоять из одного файла (должен иметь расширение .ocmod.xml) или нескольких, упакованных в архив с расширением .ocmod.zip. В архиве могут находиться XML, SQL и PHP файлы:

  • upload/*
  • install.sql
  • install.php
  • install.xml

Все файлы из папки upload будут скопированы в папку, куда установлен Opencart.

В install.sql можно добавить все необходимые SQL-запросы (create, drop, insert, update), которые должны быть исполнены при установке модуля. Каждый запрос должен заканчиваться символом ;.

Если модуль требует каких-то дополнительных действий для установки, PHP код надо разместить в файле install.php.

Остальные подробности можно будет узнать позже -- либо по мере появления новой документации по адресу https://github.com/opencart/opencart/wiki/Modification-System, либо путём изучения появляющихся модулей.

См. также:

  • Override Engine + VQmod for OpenCart 2.0 (J.Neuhoff). Это решение позволяет получить как новую систему Override Engine (OE), так и поддержку всех старых vQmod расширений (OE хорош именно для модулей, а вот для изменения шаблонов способ vQmod пока наиболее подходящий; плюс совместимость). Всё доступно свободно для скачивания и эксперименто. Предлагали Даниэлю. Кстати, автор vQmod (Qphoria) тоже высказался в топике за встраивание этого варианта OE+vQmod в Opencart 2.0. Он сказал: "Согласен. Я хочу, чтобы OE включили в ядро Opencart, а vQmod остался внешним расширением, каким он всегда был. OE или правильная система хуков -- это что-то, что ядро должно предлагать из коробки, тогда как vQmod был создан лишь как костыль, исправляющий отсутствие чего-то подобного в ядре. vQmod до сих пор имеет огромный смысл в Opencart, но я не вижу смысла в добавлении урезанного его варианта вместо того, чтобы сделать правильную систему."

SafePatch -- альтернатива vQmod

Другими словами странность того, что происходит, очевидна всем разработчикам, кроме Даниэля.

Знакомим `phpcs` (PHP CodeSniffer) и Sublime Text со стандартом оформления кода FuelPHP

- Posted in Uncategorized by

UPD: При ближайшем рассмотрении оказалось, что отличий от PSR2 больше, чем табы вместо пробелов. Чтобы сделать автоматическую проверку, надо ещё многое переделать, а где-то и дописать. Так что я поспешил: с опубликованным вариантом проверять синтаксис PHP CodeSniffer'ом на соответствие правилам пока что неудобно.


Самый простой способ - поставить в редакторе/IDE правила автоформатирования PSR-2 и заменить использование пробелов в отступах на табуляцию (этим стандарты оформления кода, принятые в FuelPHP, отличаются от PSR-2). Заодно можно включить отображение пробелов и табуляций.

Это позволит писать новый код по правилам, но огрехи в старом могут оказаться незамеченными.

Для автоматизации проверки кода существуют разные инструменты: примеры (и важность с удобством применения этого непосредственно в редакторах/IDE) есть в статье http://philsturgeon.co.uk/blog/2013/08/php-static-analysis-in-sublime-text.

Обычно они дают возможность запустить проверку, либо настроить её и показ ошибки при сохранениях файла. Последнее очень удобно, т.к. помогает исправлять обнаруженные ошибки по ходу дела и без дополнительных усилий. Ниже - рецепт по автоматизации для ST3 (а может и ST2, если плагин совместим).

Знакомим phpcs и ST3 со стандатами оформления кода FuelPHP

  • sudo apt-get install php-codesniffer
    • phpcs -i - показать список установленных стандартов. Нужен psr2 (PSR-2)
    • Если его нет - обновляем полностью CodeSniffer (просто скопировать оттуда папку с PSR2/1 стандартом недостаточно)

    • Это, конечно, грубовато - обновлять напрямую, в обход apt-get , но он считает, что установлена самая свежая версия и более правильного способа я сейчас не знаю.

      cd ~/Downloads
      wget https://github.com/squizlabs/PHP_CodeSniffer/archive/master.zip
      unzip PHP_CodeSniffer-master.zip
      cd PHP_CodeSniffer-master
      sudo cp -r --parents -t /usr/share/php/PHP/ CodeSniffer CodeSniffer.php scripts
      cd scripts
      sudo mv /usr/bin/phpcs /usr/bin/phpcs.ORIGINAL
      sudo cp -t /usr/bin/ phpcs
    • в PSR-2 используются пробелы вместо табуляций и phpcs на них ругается. Сделаем свой стандарт "FuelPHP", основанный на PSR2. Рядом с папкой PSR2 создаём FuelPHP, в которой достаточно одного файла FuelPHP/ruleset.xml :

    • <?xml version="1.0"?>
      <ruleset name="FuelPHP">
       <description>The FuelPHP coding standard.</description>
       <!-- Include the whole PSR-2 standard -->
       <rule ref="PSR2">
       <!-- Redefine 2.4 Indenting -->
       <!-- Code MUST use an indent of tabs, and MUST NOT use 4 spaces for indenting. -->
       <exclude name="Generic.WhiteSpace.DisallowTabIndent"/>
       </rule>
       <rule ref="Generic.WhiteSpace.DisallowSpaceIndent"/>
      </ruleset>

      Проверяем: phpcs -i

      The installed coding standards are Zend, FuelPHP, PHPCS, PSR2, PSR1, Squiz,
      MySource and PEAR
  • install ST3 plugin "Sublime Phpcs" http://www.soulbroken.co.uk/code/sublimephpcs/
  • check config, see HOWTO: http://philsturgeon.co.uk/blog/2013/08/php-static-analysis-in-sublime-text
    • только мы вместо "psr2" теперь напишем свой "FuelPHP" в юзеркониге:

    • Содержимое /home/rb/.config/sublime-text-3/Packages/User/phpcs.sublime-settings :

      {
          "show_debug": true,
          "phpcs_executable_path": "/usr/bin/phpcs",
          "phpcs_additional_args": {
              "--standard": "FuelPHP",
              "-n": ""
          },
      }

Автоматическая проверка в ST3 тепрь работает.

Также можно использовать отдельно: phpcs --standard=fuelphp home.php .

Opencart (admin): сортировка товаров по колонке с изображениями

- Posted in Uncategorized by

Сортировка по колонке с фото пригодится для быстрого перехода к товарам, у которых нет фото.

Делалось на последней версии с гитхаба, но должно быть аналогично для всех версий. Единственное, что может отличаться - tpl файл, т.к. админка в v2.0 существенно переделывалась. Но думаю, не составит труда адаптировать одну строчку под необходимую вам версию.

commit d19311b80b518c7b076b459985486d7d0c2190db
Author: Ruslan Brest <rb@labtodo.com>
Date:   Wed Aug 14 14:14:18 2013 +0300
    admin: add sort by "image" column (to quick access to products without images)
diff --git a/upload/admin/controller/catalog/product.php b/upload/admin/controller/catalog/product.php
index b867b0d..55cd8fc 100644
--- a/upload/admin/controller/catalog/product.php
+++ b/upload/admin/controller/catalog/product.php
@@ -450,6 +450,7 @@ class ControllerCatalogProduct extends Controller {
            $url .= '&page=' . $this->request->get['page'];
        }
                    
+       $this->data['sort_image'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.image' . $url, 'SSL');
        $this->data['sort_name'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=pd.name' . $url, 'SSL');
        $this->data['sort_model'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.model' . $url, 'SSL');
        $this->data['sort_price'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.price' . $url, 'SSL');
diff --git a/upload/admin/model/catalog/product.php b/upload/admin/model/catalog/product.php
index 9a3589e..991c868 100644
--- a/upload/admin/model/catalog/product.php
+++ b/upload/admin/model/catalog/product.php
@@ -346,6 +346,7 @@ class ModelCatalogProduct extends Model {
        $sql .= " GROUP BY p.product_id";
                    
        $sort_data = array(
+           'p.image',
            'pd.name',
            'p.model',
            'p.price',
diff --git a/upload/admin/view/template/catalog/product_list.tpl b/upload/admin/view/template/catalog/product_list.tpl
index 75cddd6..2b8aa81 100644
--- a/upload/admin/view/template/catalog/product_list.tpl
+++ b/upload/admin/view/template/catalog/product_list.tpl
@@ -29,7 +29,12 @@
           <thead>
             <tr>
               <td width="1" class="center"><input type="checkbox" onclick="$('input[name*=\'selected\']').prop('checked', this.checked);" /></td>
-              <td class="center"><?php echo $column_image; ?></td>
+
+              <?php $html_class_order = 'class="' . strtolower($order) . '"'; ?>
+
+              <td class="center">
+                <a href="<?php echo $sort_image; ?>" <?php echo ($sort == 'p.image') ? $html_class_order : '' ?>><?php echo $column_image; ?></a>
+              </td>
               <td class="left"><?php if ($sort == 'pd.name') { ?>
                 <a href="<?php echo $sort_name; ?>" class="<?php echo strtolower($order); ?>"><?php echo $column_name; ?></a>
                 <?php } else { ?>

Opencart: вывод производителей в своём порядке вместо алфавитного

- Posted in Uncategorized by

Для тех, кто хочет выводить страницу производителей (брендов) в своём порядке, а не в алфавитном, Сегодняшний рецепт. Надо изменить файл catalog/controller/product/manufacturer.php.

Ищем строку #33:

$results = $this->model_catalog_manufacturer->getManufacturers();

её надо заменить на

$results = $this->model_catalog_manufacturer->getManufacturers(
    array('sort' => 'sort_order', 'order'=>'ASC')
    );

и чуть ниже - часть

foreach ($results as $result) {
    if (is_numeric(utf8_substr($result['name'], 0, 1))) {
        $key = '0 - 9';
    } else {
        $key = utf8_substr(utf8_strtoupper($result['name']), 0, 1);
    }

изменить на:

foreach ($results as $result) {
    /*
    if (is_numeric(utf8_substr($result['name'], 0, 1))) {
        $key = '0 - 9';
    } else {
        $key = utf8_substr(utf8_strtoupper($result['name']), 0, 1);
    }
    */
    $key = $this->language->get('button_view');

То же самое в виде diff-файла

diff --git a/upload/catalog/controller/product/manufacturer.php b/upload/catalog/controller/product/manufacturer.php
index 3b0b701..1071612 100644
--- a/upload/catalog/controller/product/manufacturer.php
+++ b/upload/catalog/controller/product/manufacturer.php
@@ -30,14 +30,19 @@ class ControllerProductManufacturer extends Controller {
 
        $this->data['categories'] = array();
 
-       $results = $this->model_catalog_manufacturer->getManufacturers();
+       $results = $this->model_catalog_manufacturer->getManufacturers(
+           array('sort' => 'sort_order', 'order'=>'ASC')
+           );
 
        foreach ($results as $result) {
+           /*
            if (is_numeric(utf8_substr($result['name'], 0, 1))) {
                $key = '0 - 9';
            } else {
                $key = utf8_substr(utf8_strtoupper($result['name']), 0, 1);
            }
+           */
+           $key = $this->language->get('button_view');
 
            if (!isset($this->data['categories'][$key])) {
                $this->data['categories'][$key]['name'] = $key;

Проверялось на версии Opencart 2.0.

Opencart: иконки в breadcrumbs

- Posted in Uncategorized by

Как изменить символ "»" на собственную иконку?

Opencart 2.0

Для этого в файле catalog/view/theme/default/stylesheet/stylesheet.css

надо найти

.breadcrumb li + li:before {
    content: '»';
    padding: 0px 5px 0px 5px;
}

и заменить на что-то наподобие:

.breadcrumb li + li:before {
    content: url('../image/success.png');
    padding: 0px 5px 0px 5px;
}

Второй способ - использовать специальные шрифты с иконками.

Opencart 1.5.x (возможно, и 1.4.x тоже)

Для более ранних версий Opencart (вплоть до 1.5.5.1) надо изменить текст `text_separator` в языковых файлах:

$_['text_separator'] = '<img src="image/flags/ua.png" height="42" width="42"/>';

Искать в `catalog/language/english/english.php`, `catalog/language/russian/russian.php` и т.п.

Lubuntu and touchpad: horisontal scrolling, disable touchpad when typing

- Posted in Uncategorized by

Наконец дошли руки починить пару давно мешающих проблем с тачпадом (Lubuntu @ Asus 1015BX).

Первая: почему-то отключен горизонтальный скроллинг. Включаем оба варианта (прокрутка по кромке тачпада и двумя пальцами):

synclient HorizEdgeScroll=1 HorizTwoFingerScroll=1

Вторая: в настройках нет возможности отключать тачпад во время работы с клавиатурой, и это мешает при работе с текстами и кодом просто неимоверно. Вечно обнаруживаешь, что курсор куда-то перескочил и часть текста набралась чёрти где... Лечится командой

syndaemon -t -k -i 2 -d

Что означают параметры:

  • -i 2 -- устанавливает время задержки в 2 секунды (сколько ждать после последнего нажатия на клавиши перед тем, как снова включить тачпад);
  • -t -- не запрещать движения мыши при наборе текста, а только нажатия (клики) и скроллинг;
  • -k -- игнорировать клавиши-модификаторы при мониторинге активности клавиатуры (таким образом, разрешаем действия наподобие Ctrl+Click);
  • -d -- стартовать как служба (daemon), в фоне.

Вот и всё. Места, куда можно поместить эти команды для автостарта:

  • ~/.profile
  • Lubuntu: /etc/xdg/lxsession/Lubuntu/autostart

На Asus 1015BX также не работает Fn+F3 (выкл/вкл тачпад). Надо бы ещё сообразить, как на эту клавишу прицепить обработку пары простых команд synclient TouchpadOff=1 и synclient TouchpadOff=0. Хотя мне это уже и не надо -- прекрасно работает автоматическое отключение и включение тачпада.

Shaarli: добавил поддержку Markdown

- Posted in Uncategorized by

прикрутил поддержку Markdown в описаниях. Это оказалось чуть ли не пятиминутным делом. Готовые библиотеки скачиваются на счёт "раз-два", а несколько мест, где происходит обработка описаний при выводе на экран, позаимствовал из готового пулл-реквеста в Github-репозиторий Shaarli (PR#63). Их там всего 3-4, так что всё, что оставалось сделать - просто изменить подключаемые библиотеки и поменять вызовы на `Markdown()`.

Меня интересовало решение для PHP 5.2, а не 5.3 и выше - на сервере, где лежит мой сайт, версию PHP выбрать нельзя. Там 5.2.17. Кого интересует PHP 5.3+, см. оригинальный пулл-реквест. Там и более свежая Markdown библиотека используется. Которая, кстати, в будущем останется одна (начиная с 2014 года).

Также задумался о том, что неплохо было бы мульти-юзер версию иметь на примете. У нас с парой человек как-то возникало несколько раз желание использовать делишес для сбора ссылок в отдельных проектах или компаниях. Букмарклетами ссылки добавлять в хранилище легко и просто, а тегами они прекрасно быстро сортируются. И не нужны никакие вики: туда сначала надо зайти, найти, куда вписать, открыть редактор, найти там место, скопировать и оформить ссылку. Понятное дело, что на это хватает только самых упёртых. Сравните с кликом по кнопке в тулбаре и вписыванием нескольких тегов для категоризации. Всё остальное происходит само.

Итак, недолгий гуглёж показал, что ближайшая альтернатива, на которую я буду смотреть -- Scuttle (multiuser Delicious-clone, PHP, MySQL). Остальные (не только на PHP) -- см. tags: delicious + alternative. Но мне они менее интересны в силу разных причин.

Бекап Opencart сайта &#45; checklist

- Posted in Uncategorized by

Сайт обычно располагается в папке `public_html`.

  1. Папки `admin`, `catalog`, `download`, `system`, а также файлы `.htaccess`, `config.php`, `humans.txt`, `robots.txt`, `yandex_*.txt` -- это всё движок магазина. Те, кто использует VQmod, должны добавить к списку ещё папку `vqmod`.
    • файлы с точкой впереди - системные/скрытые. Поэтому их может быть не видно и надо включить в настройках FTP-клиента опцию их показа. `.htaccess` очень важен для работы сайта. Если у него есть расширение (.TXT или любое другое) - значит он сервером не используется (отключен). В этом случае не будут работать SEO URL;
    • в указанных папках есть 2 "лишние", их нежелательно включать в бекап: `system/cache`, `system/logs`. Это кешированные файлы и лог ошибок. Они нужны для работы и диагностики, но хранить их - смысла мало. Особенно если они большого объёма;
    • если вы пользуетесь VQmod-ом: папку `vqmod/logs` желательно исключить из бекапа. Папку 'vqmod/vqcache' можно бекапить, а можно и нет. Самое ценное здесь - содержимое `vqmod/xml`. Остальное несложно восстановить.
  2. Вторая важная часть сайта - картинки/фото.
  3. Они находятся в папке `image` (`public_html/image`). Оригиналы картинок - в папке `image/data`. Это самое ценное. Остальное несложно восстановить.

    • Что здесь бекапить: всю папку `image` за исключением `image/cache`
    • `image/cache` очень объемная. Эти файлы генерируются сайтом на лету при просмотре сайта. Ссылки на них могут использоваться в `sitemap.xml`.

  4. Третья критически важная часть сайта - база данных магазина. Её через FTP не скопируешь. Её надо бекапить либо Adminer-ом, либо phpMyAdmin (обычно есть в панели управления хостинга).

Opencart 1.5.5 (admin): показ SEO Keyword в списке категорий

- Posted in Uncategorized by

Добавляется колонка на странице категорий в админ-части:

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

commit 078537f3d45ecbf7908169e55251243c463ac593
Author: Ruslan Brest <rb@labtodo.com>
Date:   Tue Mar 5 14:42:44 2013 +0200
    [+] Opencart 1.5.5 (admin): показ SEO Keyword в списке категорий
diff --git a/public_html/admin/controller/catalog/category.php b/public_html/admin/controller/catalog/category.php
index d82776a..32a02a4 100644
--- a/public_html/admin/controller/catalog/category.php
+++ b/public_html/admin/controller/catalog/category.php
@@ -157,6 +157,7 @@ class ControllerCatalogCategory extends Controller {
            $this->data['categories'][] = array(
                'category_id' => $result['category_id'],
                'name'        => $result['name'],
+               'keyword'     => $result['keyword'],
                'sort_order'  => $result['sort_order'],
                'selected'    => isset($this->request->post['selected']) && in_array($result['category_id'], $this->request->post['selected']),
                'action'      => $action
@@ -168,6 +169,7 @@ class ControllerCatalogCategory extends Controller {
        $this->data['text_no_results'] = $this->language->get('text_no_results');
 
        $this->data['column_name'] = $this->language->get('column_name');
+       $this->data['column_seo_keyword'] = $this->language->get('column_seo_keyword');
        $this->data['column_sort_order'] = $this->language->get('column_sort_order');
        $this->data['column_action'] = $this->language->get('column_action');
 
diff --git a/public_html/admin/language/english/catalog/category.php b/public_html/admin/language/english/catalog/category.php
index 7c26ba9..bbec2cd 100644
--- a/public_html/admin/language/english/catalog/category.php
+++ b/public_html/admin/language/english/catalog/category.php
@@ -11,6 +11,7 @@ $_['text_clear']             = 'Clear';
 
 // Column
 $_['column_name']            = 'Category Name';
+$_['column_seo_keyword']     = 'SEO Keyword';
 $_['column_sort_order']      = 'Sort Order';
 $_['column_action']          = 'Action';
 
diff --git a/public_html/admin/model/catalog/category.php b/public_html/admin/model/catalog/category.php
index a90b74c..021cbb9 100644
--- a/public_html/admin/model/catalog/category.php
+++ b/public_html/admin/model/catalog/category.php
@@ -205,7 +205,14 @@ class ModelCatalogCategory extends Model {
    } 
    
    public function getCategories($data) {
-       $sql = "SELECT cp.category_id AS category_id, GROUP_CONCAT(cd1.name ORDER BY cp.level SEPARATOR ' > ') AS name, c.parent_id, c.sort_order FROM " . DB_PREFIX . "category_path cp LEFT JOIN " . DB_PREFIX . "category c ON (cp.path_id = c.category_id) LEFT JOIN " . DB_PREFIX . "category_description cd1 ON (c.category_id = cd1.category_id) LEFT JOIN " . DB_PREFIX . "category_description cd2 ON (cp.category_id = cd2.category_id) WHERE cd1.language_id = '" . (int)$this->config->get('config_language_id') . "' AND cd2.language_id = '" . (int)$this->config->get('config_language_id') . "'";
+       $sql = "SELECT cp.category_id AS category_id, GROUP_CONCAT(cd1.name ORDER BY cp.level SEPARATOR ' > ') AS name, c.parent_id, c.sort_order, ua.keyword";
+       $sql .= " FROM " . DB_PREFIX . "category_path cp";
+       $sql .= " LEFT JOIN " . DB_PREFIX . "category c ON (cp.path_id = c.category_id)";
+       $sql .= " LEFT JOIN " . DB_PREFIX . "url_alias ua ON (ua.query = CONCAT('category_id=', cp.category_id))";
+       $sql .= " LEFT JOIN " . DB_PREFIX . "category_description cd1 ON (c.category_id = cd1.category_id)";
+       $sql .= " LEFT JOIN " . DB_PREFIX . "category_description cd2 ON (cp.category_id = cd2.category_id)";
+       $sql .= " WHERE cd1.language_id = '" . (int)$this->config->get('config_language_id')
+           . "' AND cd2.language_id = '" . (int)$this->config->get('config_language_id') . "'";
        
        if (!empty($data['filter_name'])) {
            $sql .= " AND cd2.name LIKE '%" . $this->db->escape($data['filter_name']) . "%'";
diff --git a/public_html/admin/view/template/catalog/category_list.tpl b/public_html/admin/view/template/catalog/category_list.tpl
index 45ca090..0e37f56 100644
--- a/public_html/admin/view/template/catalog/category_list.tpl
+++ b/public_html/admin/view/template/catalog/category_list.tpl
@@ -23,6 +23,7 @@
             <tr>
               <td width="1" style="text-align: center;"><input type="checkbox" onclick="$('input[name*=\'selected\']').attr('checked', this.checked);" /></td>
               <td class="left"><?php echo $column_name; ?></td>
+              <td class="left"><?php echo $column_seo_keyword; ?></td>
               <td class="right"><?php echo $column_sort_order; ?></td>
               <td class="right"><?php echo $column_action; ?></td>
             </tr>
@@ -37,6 +38,7 @@
                 <input type="checkbox" name="selected[]" value="<?php echo $category['category_id']; ?>" />
                 <?php } ?></td>
               <td class="left"><?php echo $category['name']; ?></td>
+              <td class="left"><?php echo $category['keyword']; ?></td>
               <td class="right"><?php echo $category['sort_order']; ?></td>
               <td class="right"><?php foreach ($category['action'] as $action) { ?>
                 <a href="<?php echo $action['href']; ?>"><?php echo $action['text']; ?></a>
@@ -45,7 +47,7 @@
             <?php } ?>
             <?php } else { ?>
             <tr>
-              <td class="center" colspan="4"><?php echo $text_no_results; ?></td>
+              <td class="center" colspan="5"><?php echo $text_no_results; ?></td>
             </tr>
             <?php } ?>
           </tbody>

Файлы для скачивания:

Opencart 1.5.5 (admin): показ SEO Keyword в списке категорий

  • diff - для автоматического или ручного переноса изменений;
  • папка со всеми измененными файлами - для тех, кому удобней сравнивать и переносить изменения инструментами вроде WinMerge, Beyond Compare, Meld;
  • xml - для тех, кто пользуется vqMod.
Page 2 of 8