Мобильная версия - автосмена шаблона при заходе с мобильного

Правила раздела: faq.php?mode=okay
Модератор: Модераторы

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #1 makki » 17.09.2016, 20:37

Инструкция для 2-й версии OkayCMS на следующей странице
Задумался над отображением шаблона на мобильных устройствах и понял, что меня не устраивают ограничения, которые накладывает адаптивная верстка. Решил пойти в сторону автосмены шаблона при заходе с мобильного устройства и возможности переключать шаблон в клиентской части.
Выкладываю решение.

1) Подключаем библиотеку для определения устройства, с которого пользователь зашел на сайт.
Создайте в корне сайта папку classes и поместите в нее из архива файл Mobile_Detect.php или скачайте с сайта разработчиков mobiledetect[точка]net
Mobile_Detect.zip
(25.35 КБ) 51 скачивание


2) В файле api/Settings.php
2.1) Указываем названия шаблонов
После строк

Код: Выделить всё

class Settings extends Okay {
   
    private $vars = array();

добавляем

Код: Выделить всё

    private $mobile_theme = 'mobile';
    private $desktop_theme = 'desktop';

тут mobile и desktop - это названия Вашего мобильного и соответственно десктопного шаблона в админке.

2.2) подменяем название шаблона, если браузер принадлежит к мобильным устройствам.
После

Код: Выделить всё

        foreach($this->db->results() as $result) {
        -------
        }

добавляем

Код: Выделить всё

        if (isset($_SESSION['site_version'])) {
           if ($_SESSION['site_version'] == 'mobile') {
              $this->vars['theme'] = $this->mobile_theme;
           } else {
              $this->vars['theme'] = $this->desktop_theme;
           }
        } elseif (empty($_SESSION['site_version'])) {
           require_once 'classes/Mobile_Detect.php';
         $detect = new Mobile_Detect;
         if ($detect->isMobile()) {
              $this->vars['theme'] = $this->mobile_theme;
           } else {
              $this->vars['theme'] = $this->desktop_theme;
           }
       }


3) В файле index.php
3.1) Проверяем GET-запрос, запоминаем через сессию версию шаблона и делаем редирект, чтобы очистить адресную строку от параметров GET-запроса
после

Код: Выделить всё

$view = new IndexView();

добавляем

Код: Выделить всё

if (isset($_GET['v'])) {
    $_SESSION['site_version'] = $_GET['v'] == 'mobile' ? 'mobile' : 'desktop';
   header('Location:' . $view->request->url(array('v'=>null)));
   exit;
}

3.2) Добавим HTTP-заголовок Vary, чтобы сообщить поисковым системам о динамическом показе кода HTML и CSS.
после

Код: Выделить всё

header("Content-type: text/html; charset=UTF-8");

добавим

Код: Выделить всё

header("Vary: Accept-Encoding, User-Agent");


4) Для принудительного переключения на мобильный шаблон, в десктопном шаблоне в файле design/ваш_десктопный_шаблон/html/index.tpl в коде футера вместо

Код: Выделить всё

{* Копирайт *}
<div class="container p-y-1">
   © {$smarty.now|date_format:"%Y"}. <a class="link-black" href="http://okay-cms.com" target="_blank"><span data-language="{$translate_id['index_copyright']}">{$lang->index_copyright}</span></a>
</div>

добавляем

Код: Выделить всё

{* Копирайт *}
<div class="container p-y-1">
   <div class="pull-xs-left">© {$smarty.now|date_format:"%Y"}. <a class="link-black" href="http://okay-cms.com" target="_blank"><span data-language="{$translate_id['index_copyright']}">{$lang->index_copyright}</span></a></div>
   <div class="pull-xs-right"><a class="link-black" href="/?v=mobile">Мобильная версия сайта</a></div>
</div>


5) Соответственно в мобильном шаблоне в том же месте меняем на следующее:

Код: Выделить всё

{* Копирайт *}
<div class="container p-y-1">
   <div class="pull-xs-left">© {$smarty.now|date_format:"%Y"}. <a class="link-black" href="http://okay-cms.com" target="_blank"><span data-language="{$translate_id['index_copyright']}">{$lang->index_copyright}</span></a></div>
   <div class="pull-xs-right"><a class="link-black" href="/?v=desktop">Полная версия сайта</a></div>
</div>


Update. Исправлено сохранение результата определения браузера в куки.
Update2. Добавлено возможность принудительно переключать шаблоны в футере сайта.
Update3. Что нового:
- полностью переписана логика работы дополнения.
- при принудительном переключении шаблона, пользователь остается на текущей странице.
- добавлен HTTP-заголовок Vary
- в текущем исполнении дополнение можно удобно расширить так, чтобы из админки назначать мобильный и десктопный шаблон.
Update4. Заменена функция is_mobile на сторонний постоянно обновляемый PHP класс mobiledetect, актуальную версию которого всегда можно скачать на сайте разработчиков (mobiledetect[точка]net)

Спасибо за помощь всем в этой ветке и не только :)
Последний раз редактировалось makki 30.09.2016, 11:25, всего редактировалось 8 раз.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

OkayCMS M
Администратор
Аватара
OkayCMS M
Администратор
Репутация: 96
Сообщения: 975
Зарегистрирован: 12.11.2015
С нами: 3 года 8 месяцев
Сайт Skype

Сообщение #2 OkayCMS » 18.09.2016, 09:33

Мы эту функцию уже разобрали, она будет включена в новую версию Окайцмс.

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #3 makki » 18.09.2016, 09:37

Какую функцию? Функцию смены шаблона при заходе с мобильного или только определение захода с мобильного устройства?
Последний раз редактировалось makki 18.09.2016, 11:58, всего редактировалось 1 раз.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

korshunov
korshunov
Репутация: 90
Сообщения: 991
Зарегистрирован: 03.12.2015
С нами: 3 года 7 месяцев
Skype

Сообщение #4 korshunov » 18.09.2016, 11:32

makki писал(а):Решение оказалось довольно простым.
1) В файле api/Settings.php в конструкторе подменяем название шаблона, если браузер принадлежит к мобильным устройствам.

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

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #5 makki » 18.09.2016, 14:27

korshunov писал(а):По-моему, результат определения браузера стоит сохранять в куки или сессии, чтобы не гонять на каждой странице функцию is_mobile().
Исправил в изначальном сообщении темы. Спасибо
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

vvk
vvk

Сообщение #6 vvk » 20.09.2016, 07:07

скажите как должна выглядеть ссылка для смены на мобильную и дефолт

awanport
awanport
Репутация: 1
Сообщения: 4
Зарегистрирован: 20.09.2016
С нами: 2 года 10 месяцев

Сообщение #7 awanport » 20.09.2016, 09:12

vvk писал(а):скажите как должна выглядеть ссылка для смены на мобильную и дефолт
Присоединяюсь к вопросу! каким образом можно дать выбор шаблона

korshunov
korshunov
Репутация: 90
Сообщения: 991
Зарегистрирован: 03.12.2015
С нами: 3 года 7 месяцев
Skype

Сообщение #8 korshunov » 20.09.2016, 09:52

vvk писал(а):скажите как должна выглядеть ссылка для смены на мобильную и дефолт

Видимо, должна выглядеть как обычные ссылки.

awanport писал(а):Присоединяюсь к вопросу! каким образом можно дать выбор шаблона

Разными способами можно. Например, ставить ту или иную из двух ссылок в зависимости от текущего состояния. И затем программировать сами действия...

awanport
awanport
Репутация: 1
Сообщения: 4
Зарегистрирован: 20.09.2016
С нами: 2 года 10 месяцев

Сообщение #9 awanport » 20.09.2016, 10:13

korshunov писал(а):ту или иную из двух ссылок в зависимости от текущего состояния
korshunov писал(а):программировать сами действия
Расписать можете все действия поподробней? Здесь не все программисты

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #10 makki » 20.09.2016, 15:33

Попробовал передать данные методом GET и отловить их в api/Settings.php чтобы переключать шаблон. Все работает, но шаблон переключается не сразу, а только после следующего обновления страницы. Требуется помощь знатоков скрипта. Как сделать, чтобы сразу переключался шаблон?
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

awanport
awanport
Репутация: 1
Сообщения: 4
Зарегистрирован: 20.09.2016
С нами: 2 года 10 месяцев

Сообщение #11 awanport » 20.09.2016, 16:23

makki, Как сделаете поделитесь пожалуйста результатом

korshunov
korshunov
Репутация: 90
Сообщения: 991
Зарегистрирован: 03.12.2015
С нами: 3 года 7 месяцев
Skype

Сообщение #12 korshunov » 20.09.2016, 16:44

makki писал(а):Попробовал передать данные методом GET и отловить их в api/Settings.php чтобы переключать шаблон. Все работает, но шаблон переключается не сразу, а только после следующего обновления страницы. Требуется помощь знатоков скрипта. Как сделать, чтобы сразу переключался шаблон?

Видимо, все зависит от того, где и как конкретно Вы это делаете...

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #13 makki » 20.09.2016, 16:53

korshunov писал(а):Видимо, все зависит от того, где и как конкретно Вы это делаете...

Вместо того что написано в первом посте этой ветки делаю так:

1) В файле api/Settings.php после

Код: Выделить всё

        foreach($this->db->results() as $result) {
        -------
        }

Добавляю

Код: Выделить всё

        if (isset($_GET['ver'])) {
           setcookie ("theme", $_GET['ver'], time()+3600, "/");
        }
               
      if (!isset($_COOKIE['theme'])) {
         setcookie ("theme", $this->is_mobile(), time()+3600, "/");
      }
      
      if (isset($_COOKIE['theme']) && $_COOKIE['theme'] != 'pc') {
         $this->vars['theme'] = $_COOKIE['theme'];
      } 

2) В том же Settings.php добавляю функцию is_mobile()

Код: Выделить всё

   private function is_mobile() {
      $user_agent=strtolower(getenv('HTTP_USER_AGENT'));
      $accept=strtolower(getenv('HTTP_ACCEPT'));
 
      if ((strpos($accept,'text/vnd.wap.wml')!==false) ||
        (strpos($accept,'application/vnd.wap.xhtml+xml')!==false)) {
      return "mobile"; // Мобильный браузер обнаружен по HTTP-заголовкам
      }
     
      if (isset($_SERVER['HTTP_X_WAP_PROFILE']) ||
        isset($_SERVER['HTTP_PROFILE'])) {
      return "mobile"; // Мобильный браузер обнаружен по установкам сервера
      }
     
      if (preg_match('/(mini 9.5|vx1000|lge |m800|e860|u940|ux840|compal|'.
      'wireless| mobi|ahong|lg380|lgku|lgu900|lg210|lg47|lg920|lg840|'.
      'lg370|sam-r|mg50|s55|g83|t66|vx400|mk99|d615|d763|el370|sl900|'.
      'mp500|samu3|samu4|vx10|xda_|samu5|samu6|samu7|samu9|a615|b832|'.
      'm881|s920|n210|s700|c-810|_h797|mob-x|sk16d|848b|mowser|s580|'.
      'r800|471x|v120|rim8|c500foma:|160x|x160|480x|x640|t503|w839|'.
      'i250|sprint|w398samr810|m5252|c7100|mt126|x225|s5330|s820|'.
      'htil-g1|fly v71|s302|-x113|novarra|k610i|-three|8325rc|8352rc|'.
      'sanyo|vx54|c888|nx250|n120|mtk |c5588|s710|t880|c5005|i;458x|'.
      'p404i|s210|c5100|teleca|s940|c500|s590|foma|samsu|vx8|vx9|a1000|'.
      '_mms|myx|a700|gu1100|bc831|e300|ems100|me701|me702m-three|sd588|'.
      's800|8325rc|ac831|mw200|brew |d88|htc\/|htc_touch|355x|m50|km100|'.
      'd736|p-9521|telco|sl74|ktouch|m4u\/|me702|8325rc|kddi|phone|lg |'.
      'sonyericsson|samsung|240x|x320vx10|nokia|sony cmd|motorola|'.
      'up.browser|up.link|mmp|symbian|smartphone|midp|wap|vodafone|o2|'.
      'pocket|kindle|mobile|psp|treo|android|iphone|ipod|webos|wp7|wp8|'.
      'fennec|blackberry|htc_|opera m|windowsphone)/', $user_agent)) {
      return "mobile"; // Мобильный браузер обнаружен по сигнатуре User Agent
      }
     
      if (in_array(substr($user_agent,0,4),
      Array("1207", "3gso", "4thp", "501i", "502i", "503i", "504i", "505i", "506i",
            "6310", "6590", "770s", "802s", "a wa", "abac", "acer", "acoo", "acs-",
            "aiko", "airn", "alav", "alca", "alco", "amoi", "anex", "anny", "anyw",
            "aptu", "arch", "argo", "aste", "asus", "attw", "au-m", "audi", "aur ",
            "aus ", "avan", "beck", "bell", "benq", "bilb", "bird", "blac", "blaz",
            "brew", "brvw", "bumb", "bw-n", "bw-u", "c55/", "capi", "ccwa", "cdm-",
            "cell", "chtm", "cldc", "cmd-", "cond", "craw", "dait", "dall", "dang",
            "dbte", "dc-s", "devi", "dica", "dmob", "doco", "dopo", "ds-d", "ds12",
            "el49", "elai", "eml2", "emul", "eric", "erk0", "esl8", "ez40", "ez60",
            "ez70", "ezos", "ezwa", "ezze", "fake", "fetc", "fly-", "fly_", "g-mo",
            "g1 u", "g560", "gene", "gf-5", "go.w", "good", "grad", "grun", "haie",
            "hcit", "hd-m", "hd-p", "hd-t", "hei-", "hiba", "hipt", "hita", "hp i",
            "hpip", "hs-c", "htc ", "htc-", "htc_", "htca", "htcg", "htcp", "htcs",
            "htct", "http", "huaw", "hutc", "i-20", "i-go", "i-ma", "i230", "iac",
            "iac-", "iac/", "ibro", "idea", "ig01", "ikom", "im1k", "inno", "ipaq",
            "iris", "jata", "java", "jbro", "jemu", "jigs", "kddi", "keji", "kgt",
            "kgt/", "klon", "kpt ", "kwc-", "kyoc", "kyok", "leno", "lexi", "lg g",
            "lg-a", "lg-b", "lg-c", "lg-d", "lg-f", "lg-g", "lg-k", "lg-l", "lg-m",
            "lg-o", "lg-p", "lg-s", "lg-t", "lg-u", "lg-w", "lg/k", "lg/l", "lg/u",
            "lg50", "lg54", "lge-", "lge/", "libw", "lynx", "m-cr", "m1-w", "m3ga",
            "m50/", "mate", "maui", "maxo", "mc01", "mc21", "mcca", "medi", "merc",
            "meri", "midp", "mio8", "mioa", "mits", "mmef", "mo01", "mo02", "mobi",
            "mode", "modo", "mot ", "mot-", "moto", "motv", "mozz", "mt50", "mtp1",
            "mtv ", "mwbp", "mywa", "n100", "n101", "n102", "n202", "n203", "n300",
            "n302", "n500", "n502", "n505", "n700", "n701", "n710", "nec-", "nem-",
            "neon", "netf", "newg", "newt", "nok6", "noki", "nzph", "o2 x", "o2-x",
            "o2im", "opti", "opwv", "oran", "owg1", "p800", "palm", "pana", "pand",
            "pant", "pdxg", "pg-1", "pg-2", "pg-3", "pg-6", "pg-8", "pg-c", "pg13",
            "phil", "pire", "play", "pluc", "pn-2", "pock", "port", "pose", "prox",
            "psio", "pt-g", "qa-a", "qc-2", "qc-3", "qc-5", "qc-7", "qc07", "qc12",
            "qc21", "qc32", "qc60", "qci-", "qtek", "qwap", "r380", "r600", "raks",
            "rim9", "rove", "rozo", "s55/", "sage", "sama", "samm", "sams", "sany",
            "sava", "sc01", "sch-", "scoo", "scp-", "sdk/", "se47", "sec-", "sec0",
            "sec1", "semc", "send", "seri", "sgh-", "shar", "sie-", "siem", "sk-0",
            "sl45", "slid", "smal", "smar", "smb3", "smit", "smt5", "soft", "sony",
            "sp01", "sph-", "spv ", "spv-", "sy01", "symb", "t-mo", "t218", "t250",
            "t600", "t610", "t618", "tagt", "talk", "tcl-", "tdg-", "teli", "telm",
            "tim-", "topl", "tosh", "treo", "ts70", "tsm-", "tsm3", "tsm5", "tx-9",
            "up.b", "upg1", "upsi", "utst", "v400", "v750", "veri", "virg", "vite",
            "vk-v", "vk40", "vk50", "vk52", "vk53", "vm40", "voda", "vulc", "vx52",
            "vx53", "vx60", "vx61", "vx70", "vx80", "vx81", "vx83", "vx85", "vx98",
            "w3c ", "w3c-", "wap-", "wapa", "wapi", "wapj", "wapm", "wapp", "wapr",
            "waps", "wapt", "wapu", "wapv", "wapy", "webc", "whit", "wig ", "winc",
            "winw", "wmlb", "wonu", "x700", "xda-", "xda2", "xdag", "yas-", "your",
            "zeto", "zte-"))) {
      return "mobile"; // Мобильный браузер обнаружен по сигнатуре User Agent
      }
 
   return "pc"; // Мобильный браузер не обнаружен
   }


3) В дефолтном шаблоне в index.tpl добавляю такую ссылку

Код: Выделить всё

<a class="link-black" href="{$config->root_url}/?ver=mobile">Мобильная версия сайта</a>

4) В мобильном шаблоне в index.tpl добавляю такую ссылку

Код: Выделить всё

<a class="link-black" href="{$config->root_url}/?ver=pc">Полная версия сайта</a>
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

korshunov
korshunov
Репутация: 90
Сообщения: 991
Зарегистрирован: 03.12.2015
С нами: 3 года 7 месяцев
Skype

Сообщение #14 korshunov » 21.09.2016, 06:25

Пробуйте вместо

Код: Выделить всё

        if (isset($_GET['ver'])) {
           setcookie ("theme", $_GET['ver'], time()+3600, "/");
        }
     


поставить

Код: Выделить всё

        if (isset($_GET['ver'])) {
           setcookie ("theme", $_GET['ver'], time()+3600, "/");
           $_COOKIE['theme']=$_GET['ver'];
        }
     


И аналогично в следующем фрагменте.

И условие $_COOKIE['theme'] != 'pc' непонятно зачем добавлено. По-моему, оно только блокирует переключение на pc-версию...


На странице
https://php.ru/manual/function.setcookie.html
Можно видеть:

setcookie() задает cookie, которое будет передано клиенту вместе с другими HTTP заголовками...
После передачи клиенту cookie станут доступны через массивы $_COOKIE...

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #15 makki » 21.09.2016, 07:01

korshunov писал(а):Пробуйте вместо
КОД: ВЫДЕЛИТЬ ВСЁ
        if (isset($_GET['ver'])) {
           setcookie ("theme", $_GET['ver'], time()+3600, "/");
        }
     

поставить

КОД: ВЫДЕЛИТЬ ВСЁ
        if (isset($_GET['ver'])) {
           setcookie ("theme", $_GET['ver'], time()+3600, "/");
           $_COOKIE['theme']=$_GET['ver'];
        }
     

И аналогично в следующем фрагменте.
Спасибо. Теперь все в порядке.

И условие $_COOKIE['theme'] != 'pc' непонятно зачем добавлено. По-моему, оно только блокирует переключение на pc-версию...
Оно там нужно. Потому что логика такова, что название стандартного шаблона - любое, которое в админке отмечено как текущая тема. Т.е. она не должна обязательно называться pc

Внес исправления в первый пост в этой теме.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

korshunov
korshunov
Репутация: 90
Сообщения: 991
Зарегистрирован: 03.12.2015
С нами: 3 года 7 месяцев
Skype

Сообщение #16 korshunov » 21.09.2016, 07:16

makki писал(а):Оно там нужно. Потому что логика такова, что название стандартного шаблона - любое, которое в админке отмечено как текущая тема. Т.е. она не должна обязательно называться pc

Ничего не понятно.
По-моему, в текущем виде, когда пользователь в мобильном шаблоне кликнет на
href="{$config->root_url}/?ver=pc"
то переключения шаблона НЕ произойдет и он останется в мобильной версии.
Так и надо?

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #17 makki » 21.09.2016, 07:25

korshunov писал(а):Ничего не понятно.
По-моему, в текущем виде, когда пользователь в мобильном шаблоне кликнет на
href="{$config->root_url}/?ver=pc"
то переключения шаблона НЕ произойдет и он останется в мобильной версии.
Так и надо?
Переключение произойдет потому в Settings.php мы добавляем код после

Код: Выделить всё

        // и записываем их в переменную
        foreach($this->db->results() as $result) {
            if(!($this->vars[$result->name] = @unserialize($result->value))) {
                $this->vars[$result->name] = $result->value;
            }
        }

В этом цикле берется название стандартного шаблона из базы. Эти настройки перезаписываются при каждом обновлении страницы.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

korshunov
korshunov
Репутация: 90
Сообщения: 991
Зарегистрирован: 03.12.2015
С нами: 3 года 7 месяцев
Skype

Сообщение #18 korshunov » 21.09.2016, 07:43

Да, так. Уловил идею.
Но в таком случае лучше бы все-таки это условие $_COOKIE['theme'] != 'pc' убрать, а вместо него поставить проверку того, что $_COOKIE['theme'] - название существующего шаблона.

И для полного счастья - в настройках вводить имя мобильного шаблона...

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #19 makki » 22.09.2016, 13:58

Полностью переписана логика работы дополнения. Обновил инструкцию в шапке.

В текущем исполнении дополнение удобно расширить так, чтобы из админки назначать мобильный и десктопный шаблон.
Нет времени допиливать, лично мне достаточно этого. На мой взгляд будет удобнее назначать шаблоны в секции админки Шаблоны. Соответственно надо будет вносить правки в backend/ThemeAdmin.php и backend/design/html/theme.tpl
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS

makki
makki
Репутация: 152
Сообщения: 436
Зарегистрирован: 12.08.2016
С нами: 2 года 11 месяцев
Откуда: Киев
Сайт Skype

Сообщение #20 makki » 29.09.2016, 17:25

Добавил HTTP-заголовок Vary в соответствии с рекомендациями Google, чтобы сообщить поисковым системам о динамическом показе кода HTML и CSS.

Добавлено спустя 14 часов 31 минуту:
Вместо функции is_mobile(), добавлена сторонняя постоянно обновляемая библиотека mobiledetect для определения устройства, с которого пользователь зашел на сайт. Актуальную версию PHP класса всегда можно скачать на сайте разработчиков (mobiledetect[точка]net)
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS


Название раздела: Полезные решения для OkayCMS
Правила раздела: faq.php?mode=okay

Быстрый ответ


Введите код в точности так, как вы его видите. Регистр символов не имеет значения.
Код подтверждения

   

Вернуться в «Полезные решения для OkayCMS»

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 1 гость