Добавление собственных настроек в тему Drupal 7

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

29.11.2013
39 комментариев
11 мин.

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

Наверное случались ситуации, да чего уж там, сейчас, наверное, каждый второй проект сталкивается с тем, что банально, клиент спрашивает: “А как поменять мне ссылку на группу в ВК?” или “Как поменять телефон\адрес”. Эти вопросы зачастую возникают когда тема сайта достаточно проработана и для телефона\адреса или соц. кнопок есть собственное оформление которое не редактируется иначе как правкой темы. Что же делать в таком случае? Создавать собственные настройки для темы!

Банальный пример собственных настроек темы на моём блоге.

Пример на блоге

Изначально они были намертво вбиты в тему, но когда я решил их изменить, я столкнулся с тем, что мне надо лезть на ftp, править тему. А что если у меня page--*.tpl.php больше 2 (page.tpl.php и page--front-tpl.php)? Получается полнейший садизм и трата времени напрасно, поэтому я просто сделал себе соответствующие настройки в тему.

Настройки

Подготовка

Для реализации нам нужна тема, в которую мы будем добавлять собственные настройки, руки и поверхностное знание Form API, ну или хотя бы умение быстро разбираться не в сложных вещах :)

А теперь к делу

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

function THEMENAME_form_system_theme_settings_alter(&$form, &$form_state, $form_id = NULL)  {
  // Work-around for a core bug affecting admin themes. See issue #943212.
  if (isset($form_id)) {
    return;
  }
  // Тут будет наш код.
}

И всё! Теперь осталось всего-лишь добавить наши необходимые поля. Для начала давайте добавим поле для адреса.

Для этого, используя Form API мы добавляем текстовое поле (textfield). Оно вполне подходит для ввода строкового адреса.

$form['company_address'] = array(
  '#type' => 'textfield',
  '#title' => 'Адрес компании',
  '#default_value' => theme_get_setting('company_address'),
  '#size' => 60,
  '#maxlength' => 128,
  '#required' => FALSE,
);

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

Например, чтобы получить значение поля с адресом компании, нам необходимо воспользоваться функцией вот так: print theme_get_settings(‘company_address’);.

Как показал опыт, лучше всего эти вызовы оборачивать в условие

if (theme_get_setting(‘company_address’)) {
	print theme_get_setting(‘company_address’);
}

Это позволит избежать множества ошибок, которые, как правило, всплывают если принтить значение а его попросту нету или при переносе сайта. Банально на локалке всё в тихаря пашет, а на drupalhosting без такой обертки выбьет белый экран смерти.

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

Парочка примеров напоследок

Добавление раздела для наших полей, чтобы их делить на логически связанные настройки для юзера.

$form['other'] = array(
  '#type' => 'fieldset',
  '#title' => 'Дополнительные настройки',
  '#weight' => 5,
  '#collapsible' => TRUE,
  '#collapsed' => FALSE,
);

Добавление текстовой области с форматированием в этот самый раздел, а также если подключены редакторы, то например и подтянется CKEditor.

$form['other']['text_with_format'] = array(
  '#type' => 'text_format',
  '#title' => 'Текст',
  '#default_value' => theme_get_setting('text_with_format')['value'],
  '#format' =>  theme_get_setting('text_with_format')['format'],
  '#weight' => 0,
);

И самое интересное - добавление файла. Немного теории. После загрузки файла через друпал форму, файл загружается, но на время (~6 часов), т.е. на нем весит статус “Временный” и если не присвоить другой, он попросту спустя 6 часов по первому же крону удалится.

Решение в общем-то очевидное, нужно файлу дать статус постоянного и прогнать через file_save(). Но вот незадача, в теме нельзя (!) хукнуть субмит формы. И тут либо надо писать кастомный модуль, что в общем то дико, для того чтобы добавить поле в настройки, либо поставить какой-никакой, зато надежный костыль. Итак приступим.

$form['other']['background_image'] = array(
  '#title' => "Фоновая картинка",
  '#type' => 'managed_file',
  '#required' => FALSE,
  '#description' => "Картинка для фона.",
  '#default_value' => theme_get_setting('background_image'),
  '#upload_location' => 'public://',
  '#upload_validators' => array(
    'file_validate_extensions' => array('gif png jpg jpeg'),
  ),
);

Этим кодом мы добавили поле для аплоада картинки, которая будет загружаться в публичное файлохранилище. Все будет работать! Но как я и писал, спустя 6 часов первый же крон удалит вашу картинку. Для этого мы ставим вот такой вот костыль:

// Сохраняем картинку, если ей присвоен статус "временно".
$image_custom_index = theme_get_setting('background_image');
if ($image_custom_index) {
  // Берем файл ID.
  $fid = theme_get_setting('background_image');
  // Грузим наш файлик.
  $file = file_load($fid);
  // Если статус действительно "Временно", то...
  if ($file->status == 0) {
    // Устанавливаем нормальный статус.
    $file->status = FILE_STATUS_PERMANENT;
    // Сохраняем наш файл.
    file_save($file);
  }
}

Вот такие пироги) О проблеме знают, существует множество issue, есть патчи, которые даже работают, когда будет в ядре 7 неизвестно.

Вот что в итоге получили.

Итоговая форма
Полный, завершенный код theme-settings.php с этими настройками.
function THEMENAME_form_system_theme_settings_alter(&$form, &$form_state, $form_id = NULL)  {
  // Work-around for a core bug affecting admin themes. See issue #943212.
  if (isset($form_id)) {
    return;
  }

  // Данные из поля получаются через theme_get_setting('comapny_address').
  $form['company_address'] = array(
    '#type' =?> 'textfield',
    '#title' => 'Адрес компании',
    '#default_value' => theme_get_setting('company_address'),
    '#size' => 60,
    '#maxlength' => 128,
    '#required' => FALSE,
  );

  $form['other'] = array(
    '#type' => 'fieldset',
    '#title' => 'Дополнительные настройки',
    '#weight' => 5,
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );

  // Данные из поля получаются через theme_get_setting('text_with_format').
  $form['other']['text_with_format'] = array(
    '#type' => 'text_format',
    '#title' => 'Текст',
    '#default_value' => theme_get_setting('text_with_format')['value'],
    '#format' =>  theme_get_setting('text_with_format')['format'],
    '#weight' => 0,
  );

  // Данные из поля получаются через theme_get_setting('text_with_format')['value'].
  $form['other']['text_with_format'] = array(
    '#type' => 'text_format',
    '#title' => 'Текст',
    '#default_value' => theme_get_setting('text_with_format')['value'],
    '#format' =>  theme_get_setting('text_with_format')['format'],
    '#weight' => 0,
  );

  // Чтобы получить картинку, мы делаем следующее:
  // $image = theme_get_setting('background_image');
  // $image_url = file_create_url('background_image', file_load($image)->uri);
  // В $image_url будет привычная всем ссылка на картинку.
  $form['other']['background_image'] = array(
    '#title' => "Фоновая картинка",
    '#type' => 'managed_file',
    '#required' => FALSE,
    '#description' => "Картинка для фона.",
    '#default_value' => theme_get_setting('background_image'),
    '#upload_location' => 'public://',
    '#upload_validators' => array(
      'file_validate_extensions' => array('gif png jpg jpeg'),
    ),
  );

  // Сохраняем картинку, если ей присвоен статус "временно".
  $image_custom_index = theme_get_setting('background_image');
  if ($image_custom_index) {
    // Берем файл ID.
    $fid = theme_get_setting('background_image');
    // Грузим наш файлик.
    $file = file_load($fid);
    // Если статус действительно "Временно", то...
    if ($file->status == 0) {
      // Устанавливаем нормальный статус.
      $file->status = FILE_STATUS_PERMANENT;
      // Сохраняем наш файл.
      file_save($file);
    }
  }
}

Комментарии

Саша   пн, 02/12/2013 - 21:58

Отличный пост, Никита!

Монжо задать пару вопросов?

  1. Т.е. если даже форму сохранили, то файл картинки всё равно удалится по крону?

  2. А как сделать отдельную вкладку в настройках темы с нишими кастомными настройками?

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

 

Niklan   пн, 02/12/2013 - 22:04
  1. Да. Картинка будет вызываться как положено, все будет хорошо. Но через 6 часов слетит и после сброса кеша её уже нигде не будет.

  2. Не знаю, не пробовал. Попробую, если разберусь напишу статью. Я тоже думаю как допустим зеновские конфиги прятать. Хайдом и прочим бредом очень криво получается, и форма слетает. Скорее всего проще делать врапперы с классом на дисплой нон. А вкладки... я думаю что это маловероятно, ведь это форма а не пейдж. Это надо сначала сделать страницу-вкладку,а уже затем туда форму нашу сливать.

  3. Я делаю через найстроки темы. Зачем через ноду. Она ведь для этого еще и страницу резервирует. Её надо перекрывать для поисковиков и т.д. и т.п. Это гемор. А тема меняется и там появляются\убираются некоторые поля. Опять искать ноду и править чтоли. А так это настройки для конкретной темы получаются.

Саша   пн, 02/12/2013 - 22:25

Спасибо за быстрый ответ!

Про вынесение настроек в ноду. Я не утверждаю, что так нужно делать, но не является ли это как раз хорошим решением для кастомных настроек?

Ну, смотрите, какие плюсы мне тут видны:

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

б) Прятать от поисковиков? Так одна строчка же в роботсе всего, нет?

в) У секретарши в админке будет ссылка «Настройки», которая будет показывать эту ноду с нужными полями, ничего лишнего она не уидит и не испортит. Телефон изменился — ввела другой, сохранила.

 

А тема меняется и там появляются\убираются некоторые поля. Опять искать ноду и править чтоли. А так это настройки для конкретной темы получаются.

Ну, это ведь речь уже о кастомной теме. Конечно, при смене темы нужно будет наши поля (из этой одной ноды с настройками) засунуть по нужным местам тпл (через print) новой темы.

И вопрос изменений при смене тему тут не очень актуален. Ведь у любого достаточно кастомизированного сайта при смене темы отвалится много чего.

Т.е. всё перечисленное выглядит скорее как плюсы такого решения, нет? А какие ещё существенные минусы вы бы могли назвать?

Niklan   пн, 02/12/2013 - 22:35

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

Вообще, как по мне, клиенту нужно отдавать сайт с двумя юзерами, админом что по дефолту в друпале, и некий адмиинстратор который может набор-минимум. Добавление, редактирование контента, комментарии, если магазин то управлять заказами и т.д. Никаких технических настроек. А в довесок к этому создавать свой кастом модуль, где создать специальную, собственную админку на тех же формах и пейджах. Оформить как положено и т.д. Но такие админки есть смысл писать только под действительно крупные проекты, а всякую мелочь можно скинуть на тему.

По крайней мере в моих проектах решение в качестве ноды точно не найдет применения. Я очень щепитилен к такому. Меня очень выбешивает тип содержимого webform, который создается при включении одноименного модуля. Сразу сношу и навешиваю возможности форм на обычный пейдж =\ Админка чище и клиент не задает а что такое Вебформ, а в русском варианте и вовсе "Опросник". Они думают что это опрос и сидят в непонятках.

Поэтому я поднял тему на счет того что я хочу спрятать как-то грамотно настройки зена, чтобы обычный юзер не видел никаких настроек фавиконок, theme rebuld и т.д.

А как вы из ноды данные грузите, допустим поле с телефоном?

$node = node_load($nid);
$node->field_name['und'][0]'value']

Так чтоли? 

Если да, то ведь если проект будет поддерживать другой прогер, theme_get_setting() более говорящая функция)

Гость   пн, 02/12/2013 - 22:59

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

Многие drupalway-решения своими корнями застряли очень глубоко и часто это является единственным оправданием их сущестоввания в теперешнем виде, о б этом часто говорят и работающие над 8-9. Так что я как раз смотрю, если у нас есть столько проблем и странностей с набором настроек, а не сделать ли всё это проще и логичнее для юзера?

 

А в довесок к этому создавать свой кастом модуль, где создать специальную, собственную админку на тех же формах и пейджах. Оформить как положено и т.д. Но такие админки есть смысл писать только под действительно крупные проекты, а всякую мелочь можно скинуть на тему.

  Писать админку или скинуть на тему и скрывать/дорабатывать? Подход с простой нодой не проще/очевиднее ли?

 

А как вы из ноды данные грузите, допустим поле с телефоном?

$node = node_load($nid);
$node->field_name['und'][0]'value']

Так чтоли? 

Если да, то ведь если проект будет поддерживать другой прогер, theme_get_setting() более говорящая функция)

Ну, другому программисту придётся прочитать три слова про то, что поля нужно брать в ноде Nastrojki, например. Тоже ведь ничего сложного и страшного.

Я не холиварю ни в коем случае. Пытаюсь найти быстрое, простое, удобное решение.

Niklan   пн, 02/12/2013 - 23:05

В данном случае быстро, простое и удобное решение такое, каким привыкли пользоваться вы.

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

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

Саша   пн, 02/12/2013 - 23:18

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

Я ещё не создаю. Я кормил утку сегодня и подумал, что можно так попробовать делать, тогда на утку может быть больше времени. А тут ваш пост, решил сразу посоветоваться.

Да, просто создать новый типа ноды. Набить туда полей (например, телефон, который показывается в шапке, подвале и блоке на странице с заказами; и, например, поле для названия акции (скажем, секретарше нужно раз в месяц менять строчку «Акция Скидка 50%» на строчку «Акция Скидка 75%»).

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

Niklan   пн, 02/12/2013 - 23:20

Ну создание типа содержимого для единственной настройки... я на такое точно не пойду) Стараюсь в проектах все держать в чистоте и такой типа с одной нодой для меня будет грязью.

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

Саша   пн, 02/12/2013 - 23:34

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

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

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

И, кстати, говоря о чистоте. Ведь это не настройки сайта. Это просто инфа. Прятать просто инфу в раздел с настройками темы сайта — не так уж и очевидно, на мой взгляд. А так просто нода с настройками сайта содержит всё, что на этом сайте может поменять условная секретарша.

Саша   пн, 02/12/2013 - 22:28

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

Niklan   вт, 03/12/2013 - 19:46

Да где там гемор, по циклу же прогнать можно если их больше одной) Гемор было мне это решение собрать и чтобы заработало, а то я сделал сначала настройки а потом стали жаловаться что картинка пропадает. Сейчас зато всё ясно)

Саша   вт, 03/12/2013 - 02:19

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

Но нужно как-то вынести наши новые поля на отдельную страницу. Чтобы, например, можно было в тулбаре сделать большую красивую кнопку/ссылку «Настройки», которую будет юзать заказчик, не лазая туда, куда не нужно, получая отдельную таку страницу со всем, что он может поменять. И на этой странице ещё бы на табы по тематике всё разделить: контакты, инфа для блока со скидками, инфа в подвале и тп.

Вот это было бы офигенное полезное решение и отличноая статья для блога :)

Саша   вт, 03/12/2013 - 02:34

И ещё прикрутить к картинкам применение actions, конечно.

Саша   ср, 04/12/2013 - 06:16

Никита, привет!

Подумал над списком необходимого для решения с полями в Настройках темы. Получается, чтобы «догнать» вариант с новым типом ноды нам нужно реализовать:

  1. Image cache

  2. Сохранение файлов вообще

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

  4. Вынос всего этого на отдельную страницу

Ну и ещё нужно учесть, что семантически это всё именно данные сайта, это не настройки темы всё-таки.

Мне пока видится, что отдельный тип материала для всего этого выигрывает по всем параметрам.

Что скажете?

Niklan   ср, 04/12/2013 - 10:52

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

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

Вынос настроек из темы на соответствующую страницу уже потребует написание кастомного модуля с hook_menu() и drupal_load_form(), в таком смысле уже проще и пилить свою форму настроек а не грузить из настроек темы.

Image Cache? Зачем? image_style_url('stylename', $file->uri)

В общем это палка о двух концах, вам удобен с нодами, мне ближе с темами, третьим вообще кастомная админка. Да, народ высказывался пару раз на каких-то друпал докладах, воде это был Дубовский Александр. Я тоже склонен к написанию для обычных юзеров собственной мини-админки, но для маленьких и средних проектов это пустая трата времени, имеет смысл для реально крупных проектов, чтобы ну вообще, с бюджетом, временем на разработку 1-2 месяца минимум. А то ведь все хотят сайт за 3 дня, тут не до админки.

Гость   ср, 04/12/2013 - 11:13

Я тоже склонен к написанию для обычных юзеров собственной мини-админки, но для маленьких и средних проектов это пустая трата времени, имеет смысл для реально крупных проектов, чтобы ну вообще, с бюджетом, временем на разработку 1-2 месяца минимум.

Ну вот чтобы ничего не пилить, а быстро накидать полей и напринтить их в нужных местах, нода как раз ок. Задача выполняется? Да. Быстро? Да. Решение шаблонное? Да. Позволяет быстро кастомизировать и расширять вообще как угодно? Да. Нужно ли что-то учитывать при апдейтах? Нет.

 

Не знаю что сказать даже, для меня при любом раскладе создание нового типа содержимого для настроек удручает.

А чем плохо?

Niklan   ср, 04/12/2013 - 11:14

Не знаю, что-то изнутри теребит, и говорит что так неправильно)

Гость   ср, 04/12/2013 - 11:28

А, и только :) Ну если нету каких-то фактических возражений, значит можно пробовать.

У меня последние вопросы снялись после того, как я понял, что это никакие не настройки на самом деле, а такие же данные.

А как у вас, кстати, сделан редактор?

Гость   ср, 04/12/2013 - 11:32

Текстовый. Это что-то дефолтное, или кастомизированное?

Гость   ср, 04/12/2013 - 11:42

Ух-ты, я не видел этой шкурки ещё. Ну наконец-то по-человечески выглядит.

А у вставляемых картинок Друпал по-прежнему обтекание как-то криво делает и нужен wysiwyg_filter чтобы поправить?

Niklan   ср, 04/12/2013 - 11:44

Эта шкурка уже год как)

Чтобы всякого говна в коде небыло от редактора текста, надо сделать чтобы он срубал html. На уровне CKEditor. 

У меня хоть откуда данные вставляй код чистый становится. Правдка форматирование теряется, но это лучше чем потом в исходники чистить стили и классы которые он добавляет. Всё хочу написать про настройку CKEditor'a для контент-менеджеров, но забываю =\

Гость   ср, 04/12/2013 - 11:56

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

Niklan   ср, 04/12/2013 - 11:58

Попробую сегодня. Там особо то и писать нечего, ток забываю. У меня вечно идея приходит о чем написать, и когда есть время написать сожусь и вспомнить не могу чего хотел, поэтому иду на друпал.ру угорать. А моя лень не позволяет мне записывать идеи)

Гость   вс, 26/01/2014 - 15:26

Очень полезная статья. Спасибо!

Заметил только что, после удаления/замены изображения из админки, старый файл физически не удаляется.

Столкнулся еще с одной проблемой, если указывать фоновое изображени через css или прямо в .tpl через <img>, то при заливке нового приходится каждый раз подправлять код, что сводит на нет всю ту автоматизацию) Можно конечно черз js подгружать последний по времени загруженый файл, но это как моветон. Как задать автоматическое переименование файла при загрузке по шаблону?

Niklan   вс, 26/01/2014 - 15:28

Заметил только что, после удаления/замены изображения из админки, старый файл физически не удаляется

Он должен удалиться по первому крону спустя 3-4 часа.

Столкнулся еще с одной проблемой, если указывать фоновое изображени через css или прямо в .tpl через <img>, то при заливке нового приходится каждый раз подправлять код, что сводит на нет всю ту автоматизацию)

Нет не надо, вы делаете что-то не правильно. Надо не урл указывать а через php его получать. file_create_url() загуглите

Гость   вс, 26/01/2014 - 18:19

запускал крон несколкьо раз, картинки не удаляются.

function wb_clear_form_system_theme_settings_alter(&$form, &$form_state, $form_id = NULL)  {

  if (isset($form_id)) {
    return;
  }
    
  $form['other']['background_image'] = array(
    '#title' => "Фоновая картинка",
    '#type' => 'managed_file',
    '#required' => FALSE,
    '#description' => "Картинка для фона.",
    '#default_value' => theme_get_setting('background_image'),
    '#upload_location' => 'public://bg/',
    '#upload_validators' => array(
      'file_validate_extensions' => array('gif png jpg jpeg'),
    ),
  );

   // Сохраняем картинку, если ей присвоен статус "временно".
  $image_custom_index = theme_get_setting('background_image');
  if ($image_custom_index) {
    $fid = theme_get_setting('background_image');
    $file = file_load($fid);
    if ($file->status == 0) {
      $file->status = FILE_STATUS_PERMANENT;
      file_save($file);
    }
  }
 
}

Niklan   вс, 26/01/2014 - 18:53

Файл не тупо по крону удаляется. На нем метка вешается что не используется, и только спустя 3-4 часа, когда пройдет первый крон по истечении этого времени она удалится физически. А так он крон видит что не прошло 3-4 часа и игнорит удаление.

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

юзер   пн, 27/01/2014 - 17:28

Как я с свое время с этим удалением по крону бился... не в страшной сказке... на работе файл грузишь, из дома открываешь -- пусто...

d.org перекопол частым ситом, ни один костыль толком не заработал... Решил кастом модулем, но это был кривой путь...

Рома   пт, 31/01/2014 - 17:49

Добрый день. прошу прощения. но у меня не работает поле изображения.

вот мой файл theme-settings.php

<?php

function artforce_form_system_theme_settings_alter(&$form, &$form_state, $form_id = NULL)  {
  // Work-around for a core bug affecting admin themes. See issue #943212.
  if (isset($form_id)) {
    return;
  }

  $form['other'] = array(
    '#type' => 'fieldset',
    '#title' => 'Дополнительные настройки',
    '#weight' => 5,
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );

  // Чтобы получить картинку, мы делаем следующее:
  // $image = theme_get_setting('background_image');
  // $image_url = file_create_url('background_image', file_load($image)->uri);
  // В $image_url будет привычная всем ссылка на картинку.
  $form['other']['loader'] = array(
    '#title' => "Загрузчик",
    '#type' => 'managed_file',
    '#required' => FALSE,
    '#description' => "Картинка для загрузчика.",
    '#default_value' => theme_get_setting('loader'),
    '#upload_location' => 'public://',
    '#upload_validators' => array(
      'file_validate_extensions' => array('gif png jpg jpeg'),
    ),
  );
 
  // Сохраняем картинку, если ей присвоен статус "временно".
  $image_custom_index = theme_get_setting('loader');
  if ($image_custom_index) {
    // Берем файл ID.
    $fid = theme_get_setting('loader');
    // Грузим наш файлик.
    $file = file_load($fid);
    // Если статус действительно "Временно", то...
    if ($file->status == 0) {
      // Устанавливаем нормальный статус.
      $file->status = FILE_STATUS_PERMANENT;
      // Сохраняем наш файл.
      file_save($file);
    }
  }
}

?>

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

подскажите, пожалуйста, что это может быть?

Рома   пт, 31/01/2014 - 21:08

не знаю как у других, но у меня заработало только после того, как я добавил сточку
file_usage_add($file, 'core', 'theme', $fid);
после
file_save($file);

Станислав   вс, 13/07/2014 - 22:01

У меня та же ерунда, может кто знает в чем дело? 

tvinzz   пт, 08/01/2016 - 00:20

"У меня та же ерунда, может кто знает в чем дело?"
FILE_STATUS_PERMANENT замени на 1 и ошибка пропадет

John   вс, 17/02/2019 - 15:18

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

После file_save($file); вставляем следующее: file_usage_add($file, 'air', 'theme', 1);

Стало сохранятся. На всякий, для таких же как я, код полностью:

$form['brand_navbar_img'] = array( '#title' => "Логотип в навигации", '#type' => 'managed_file', '#required' => FALSE, '#description' => "Загрузите его в формате PNG. Параметры установите в CSS коде темы.", '#default_value' => theme_get_setting('brand_navbar_img'), '#upload_location' => 'public://brand/', '#upload_validators' => array( 'file_validate_extensions' => array('png'), ), );

$image_custom_index = theme_get_setting('brand_navbar_img'); if ($image_custom_index) { $fid = theme_get_setting('brand_navbar_img'); $file = file_load($fid); if ($file->status == 0) { $file->status = 1; file_save($file); file_usage_add($file, 'air', 'theme', 1); } }

John   вс, 17/02/2019 - 19:32

Поправка, в file_usage_add($file, 'air', 'theme', 1); "air" - название вашей темы.

=============================================================

Да, и на всякий случай, чтобы вывести в page.tpl.php адресом (url) картинки логотип из настроек темы, пишем следующее:

  <?php if (theme_get_setting('brand_navbar_img')): ?>
    <a class="navbar-brand pull-left" href="<?php print $front_page; ?>" alt="<?php print t('Home'); ?>">
      <img src="<?php print file_create_url(file_load(theme_get_setting('brand_navbar_img'))->uri); ?>"/>
    </a>
  <?php endif; ?>
Георгий   вт, 08/10/2019 - 09:36

У меня после сохранения темы выдает такую ошибку: Fatal error: Call to undefined function at_core_settings_validate() in S:\mysite\includes\form.inc on line 1524 И не сохраняет. Использую Adaptive Theme