суббота, 28 января 2012 г.
tt_news - добавление новых полей к плагину
Чтобы лучше понять задачу ради которой я решил добавить к tt_news ряд полей, читайте первую часть.
Для того, чтобы к любому расширению Typo3 добавить новое поле, не нужно курочить тело плагина (экста). Это - плохой тон, потому что после очередного обновления данного плагина все ваши изменения будут удалены. Хороший тон - сделать новый плагин. Причем, один такой дополнительный плагин может расширять несколько экстов Typo3 одновременно.
Создать новое расширение можно с помощью инструмента - kickstarter. Но в данной ситуации я поступил иначе. Я скачал и установил уже готовый плагин - ttnewsfield, который добавляет к tt_news одно единственное поле - tx_ttnewsfield_linktitle. Этот плагин послужил мне замечательной стартовой площадкой для добавления множества других полей.
Рассмотрим добавление 5 различных полей: обычное текстовое поле, поле в виде выпадающего списка, поле ссылающееся на запись из другой таблицы (отношение 1:1), поле ссылающееся на записи из другой таблицы (отношение 1:n), IRRE поле.
Добавление обычного текстового поля
Все что нужно для работы - это текстовый редактор и 3 файла ранее установленного ttnewsfield: ext_tables.sql, locallang_db.xml и ext_tables.php. Хотя, по-большому счету ext_tables.sql можно и не трогать, если менять структуру таблиц с помощью phpmyadmin или других программ. Думаю, что с этим файлом всё абсолютно понятно и я не буду о нем писать, как и о locallang_db.xml, который содержит набор текстовых констант, которые служат для отображения надписей в админке и её локализации.
Самое интересное творится в ext_tables.php. На старте содержимое файла такое:
$tempColumns = Array (
"tx_ttnewsfield_linktitle" => Array (
"exclude" => 0,
"label" => "LLL:EXT:ttnewsfield/locallang_db.xml:tt_news.tx_ttnewsfield_linktitle",
"config" => Array (
"type" => "input",
"size" => "15",
"max" => "64",
"eval" => "trim",
)
),
);
t3lib_div::loadTCA("tt_news");
t3lib_extMgm::addTCAcolumns("tt_news",$tempColumns,1);
$TCA['tt_news']['palettes']['1']['showitem'] .= ",tx_ttnewsfield_linktitle";
Поле tx_ttnewsfield_linktitle, которое добавляется в эксте мне не интересно, поэтому я его переименовал в tx_fitness_vimeo. Его задача - хранить обычный кусок html-кода.
Вот описание этого поля для админки в файле ext_tables.php:
'tx_fitness_vimeo' => Array (
'label' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tx_ttnewsirre_vimeo',
'l10n_mode' => $l10n_mode,
'config' => Array (
'type' => 'text',
'cols' => '48',
'rows' => '5',
'softref' => 'typolink_tag,images,email[subst],url',
'wizards' => Array(
'_PADDING' => 4,
'RTE' => Array(
'notNewRecords' => 1,
'RTEonly' => 1,
'type' => 'script',
'title' => 'LLL:EXT:cms/locallang_ttc.php:bodytext.W.RTE',
'icon' => 'wizard_rte2.gif',
'script' => 'wizard_rte.php',
),
)
)
),
Хочу заметить, что данные строки и все последующие являются элементами массива $tempColumns, который я переименовал в $fitnessColumns. Чтобы лучше понять значение каждого из вышеуказанных параметров элемента массива - почитайте мануал по TCA array reference. Там нет ничего сложного.
А вот так поле будет выглядеть в админке:
Чтобы отобразить содержимое данного поля на FE советую заглянуть во внутрь экста - Raw HTML in tt_news ( ttnews_html ) или Youtube for tt_news ( esg_youtubenews ). Абсолютно ничего военного они не делают. Добавляется одна строка в файл ext_localconf.php и создается дополнительный файл с 10-15 строками, в котором идет сопоставление значения нового поля с определенным маркером в html-шаблоне. Но правда, есть еще один способ вывода. Это универсальный экст - ttnewsgenericmarkers, который выводит в html-шаблон все, что угодно.
Добавление поля с фиксированным списком
Сделать дополнительное поле в виде статического списка значение тоже не сложно.
Вот пример, для поля tx_fitness_shared_office_suitability, которое может принимать всего 5 значений: 1, 2, 3, 4 и 5 (файл ext_tables.php):
"tx_fitness_shared_office_suitability" => Array (
"exclude" => 0,
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tx_ttnewsirre_shared_office_suitability",
'config' => array(
'type' => 'select',
'items' => array(
array('LLL:EXT:ttnews_fitness/locallang_db.xml:suitability.1', 1),
array('LLL:EXT:ttnews_fitness/locallang_db.xml:suitability.2', 2),
array('LLL:EXT:ttnews_fitness/locallang_db.xml:suitability.3', 3),
array('LLL:EXT:ttnews_fitness/locallang_db.xml:suitability.4', 4),
array('LLL:EXT:ttnews_fitness/locallang_db.xml:suitability.5', 5),
),
),
),
Эти 5 строк нужно добавить в файл locallang_db.xml:
<label index="suitability.1">1</label>
<label index="suitability.2">2</label>
<label index="suitability.3">3</label>
<label index="suitability.4">4</label>
<label index="suitability.5">5</label>
Если числа внутри тега label заменить на слова, то список станет более информативным.
Внешний вид такого списка в админке typo3:
Добавление поля-ссылки (отношение 1 к 1)
Ради таких полей я и решил написать данную статью. Меня давно интересовал данный вопрос. И вот, наконец-то, я его разрулил.
В предыдущем случае поле (tx_fitness_shared_office_suitability) являлось фиксированным списком из пяти значений, но что делать если нужен динамический список элементов? Тут все немного интереснее.
1. Создаем новую таблицу в БД, которая, собственно и будет содержать все значения списка.
В моем случае эта таблица имела такую структуру:
CREATE TABLE `tx_fitness_workarea` (
`uid` int(11) unsigned NOT NULL auto_increment,
`pid` int(11) NOT NULL default '0',
`tstamp` int(11) NOT NULL default '0',
`crdate` int(11) NOT NULL default '0',
`cruser_id` int(11) NOT NULL default '0',
`sys_language_uid` int(11) NOT NULL default '0',
`l18n_parent` int(11) NOT NULL default '0',
`l18n_diffsource` mediumblob NOT NULL,
`deleted` tinyint(4) NOT NULL default '0',
`is_dummy_record` tinyint(1) unsigned NOT NULL default '0',
`title` tinytext NOT NULL,
PRIMARY KEY (`uid`),
KEY `parent` (`pid`),
KEY `dummy` (`is_dummy_record`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
Самое ценное из всех полей данной таблицы, конечно же поле title. Остальные поля - служебные и интересуют больше не меня, а typo3.
В таблицу tt_news я добавил числовое поле tx_fitness_workarea, которое будет содержать uid только одной записи из таблицы tx_fitness_workarea. Вот sql-определение данного поля:
CREATE TABLE tt_news (
...
tx_fitness_workarea int(11) NOT NULL default '0',
...
);
Эти настройки ТСА сделают новое поле tx_fitness_workarea в таблице tt_news выпадающим списком, который будет наполнен строками из таблицы tx_fitness_workarea:
'tx_fitness_workarea' => array(
'exclude' => 1,
'label' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tx_ttnewsirre_workarea',
'config' => array(
'type' => 'select',
'items' => array(
array('', 0),
),
'foreign_table' => 'tx_fitness_workarea',
'foreign_table_where' => 'AND tx_fitness_workarea.pid=###STORAGE_PID### ORDER BY tx_fitness_workarea.title',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
'wizards' => array(
'_PADDING' => 2,
'_VERTICAL' => 1,
'add' => array(
'type' => 'script',
'title' => 'Create new record',
'icon' => 'add.gif',
'params' => array(
'table'=>'tx_fitness_workarea',
'pid' => '###STORAGE_PID###',
'setValue' => 'prepend',
),
'script' => 'wizard_add.php',
),
'edit' => array(
'type' => 'popup',
'title' => 'Edit',
'script' => 'wizard_edit.php',
'popup_onlyOpenIfSelected' => 1,
'icon' => 'edit2.gif',
'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
),
),
),
)
Вот так поле будет выглядеть в админке:
Самое интересное, как вы уже заметили, что возле списка есть кнопки, которые позволяют редактировать значения списка и добавлять в него новые элементы. Чтобы эти кнопки работали необходимо в файл ext_tables.php вставить следующие строки:
t3lib_extMgm::allowTableOnStandardPages("tx_fitness_workarea");
$TCA['tx_fitness_workarea'] = array(
'ctrl' => array(
'title' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tx_ttnewsirre_workarea',
'label' => 'title',
//'rootLevel' => 0,
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l18n_parent',
'transOrigDiffSourceField' => 'l18n_diffsource',
'default_sortby' => 'ORDER BY title',
'delete' => 'deleted',
"iconfile" => t3lib_extMgm::extRelPath($_EXTKEY)."res/workarea.gif"
),
'interface' => array(
'showRecordFieldList' => 'sys_language_uid,l18n_parent,l18n_diffsource,title'
),
"feInterface" => $TCA["tx_fitness_workarea"]["feInterface"],
'columns' => array(
'sys_language_uid' => array(
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.language',
'config' => array(
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0),
),
),
),
'l18n_parent' => array(
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.l18n_parent',
'config' => array(
'type' => 'select',
'items' => array(
array('', 0),
),
'foreign_table' => 'tx_fitness_workarea',
'foreign_table_where' => 'AND tx_fitness_workarea.pid=###CURRENT_PID### AND tx_fitness_workarea.sys_language_uid IN (-1, 0)',
),
),
'l18n_diffsource' => array(
'config' => array(
'type' => 'passthrough',
)
),
'title' => array(
'exclude' => 0,
'label' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tx_ttnewsirre_workarea',
'config' => array(
'type' => 'input',
'size' => '30',
'eval' => 'required',
),
),
),
'types' => array(
'0' => array('showitem' => 'sys_language_uid;;;;1-1-1, l18n_parent, l18n_diffsource, title;;;;2-2-2'),
),
'palettes' => array(
'1' => array('showitem' => ''),
)
);
Хочу заметить, что эти строки уже не являются элементами массива $tempColumns ($fitnessColumns).
Теперь немного о ###CURRENT_PID### и ###STORAGE_PID###, которые поначалу вызывают недоумение. Что это такое? В принципе, имеются ввиду id фолдера или страницы содержащих (отображающие) записи таблицы tx_fitness_workarea.
Вначале у меня были какие-то ошибки при добавлении новых записей, но всё вылечилось установкой General Record Storage Page для фолдера хранящего все мои данные:
Добавление поля-ссылки (отношение один ко многим 1:n)
Ну а теперь самый сложный и самый интересный случай, когда на одну запись из родительской таблицы (tt_news) ссылается несколько записей из дочерней таблицы.
В данной ситуации обычно создают еще третью таблицу, которая является прослойкой между родительской и дочерней таблицами и содержит в себе связующие записи. Для большей ясности приведу схему структуры таблиц:
SQL для данной модели данных у меня такой:
CREATE TABLE tt_news (
...
tx_fitness_equipment text,
...
);
CREATE TABLE `tx_fitness_equipment` (
`uid` int(11) NOT NULL auto_increment,
`pid` int(11) NOT NULL default '0',
`tstamp` int(11) NOT NULL default '0',
`crdate` int(11) NOT NULL default '0',
`cruser_id` int(11) NOT NULL default '0',
`sys_language_uid` int(11) NOT NULL default '0',
`l18n_parent` int(11) NOT NULL default '0',
`l18n_diffsource` mediumblob NOT NULL,
`sorting` int(10) NOT NULL default '0',
`deleted` tinyint(4) NOT NULL default '0',
`hidden` tinyint(4) NOT NULL default '0',
`t3ver_oid` int(11) NOT NULL default '0',
`t3ver_id` int(11) NOT NULL default '0',
`t3ver_wsid` int(11) NOT NULL default '0',
`t3ver_label` varchar(30) NOT NULL default '',
`t3ver_state` tinyint(4) NOT NULL default '0',
`t3ver_stage` tinyint(4) NOT NULL default '0',
`t3ver_count` int(11) NOT NULL default '0',
`t3ver_tstamp` int(11) NOT NULL default '0',
`t3ver_move_id` int(11) NOT NULL default '0',
`t3_origuid` int(11) NOT NULL default '0',
`title` tinytext NOT NULL,
`exercises` int(11) NOT NULL default '0',
`image` varchar(255) default NULL,
PRIMARY KEY (`uid`),
KEY `parent` (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8
CREATE TABLE `tt_news_mainequipment_mm` (
`uid_local` int(11) NOT NULL default '0',
`uid_foreign` int(11) NOT NULL default '0',
`tablenames` varchar(30) NOT NULL default '',
`sorting` int(11) NOT NULL default '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Последняя таблица в своем наименовании имеет суффикс MM. Это не просто так. У Typo3 такой вид отношений между таблицами называется mm-отношения. Это довольно распространенный вид взаимосвязи, наиболее ярким примером которой могут послужить новости и их категории. Ведь одна новость может принадлежать к нескольким категориям, а одна категория может принадлежать нескольким новостям.
Итак, в ext_tables.php добавляем:
'tx_fitness_equipment' => Array (
'exclude' => 1,
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tx_ttnewsirre_equipment",
'config' => Array (
'type' => 'select',
'size' => 10,
'foreign_table' => 'tx_fitness_equipment',
'foreign_table_where' => 'ORDER BY title',
'autoSizeMax' => 50,
'minitems' => 0,
'maxitems' => 10,
'MM' => 'tt_news_mainequipment_mm',
)
),
t3lib_extMgm::allowTableOnStandardPages("tx_fitness_equipment");
$TCA["tx_fitness_equipment"] = Array (
"ctrl" => Array (
'title' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_equipment',
'label' => 'title',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l18n_parent',
'transOrigDiffSourceField' => 'l18n_diffsource',
"sortby" => "sorting",
"delete" => "deleted",
"enablecolumns" => Array (
"disabled" => "hidden",
),
"iconfile" => t3lib_extMgm::extRelPath($_EXTKEY)."res/equipment.gif",
'versioningWS' => TRUE,
'origUid' => 't3_origuid',
),
"interface" => Array (
"showRecordFieldList" => "sys_language_uid,l18n_parent,l18n_diffsource,hidden,title,image,exercises"
),
"feInterface" => $TCA["tx_fitness_equipment"]["feInterface"],
"columns" => Array (
'sys_language_uid' => array (
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.language',
'config' => array (
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
)
)
),
'l18n_parent' => array (
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.l18n_parent',
'config' => array (
'type' => 'select',
'items' => array (
array('', 0),
),
'foreign_table' => 'tx_fitness_equipment',
'foreign_table_where' => 'AND tx_fitness_equipment.pid=###CURRENT_PID### AND tx_fitness_equipment.sys_language_uid IN (-1,0)',
)
),
'l18n_diffsource' => array (
'config' => array (
'type' => 'passthrough'
)
),
"hidden" => Array (
"exclude" => 1,
"label" => "LLL:EXT:lang/locallang_general.xml:LGL.hidden",
"config" => Array (
"type" => "check",
"default" => "0"
)
),
"title" => Array (
"exclude" => 1,
'l10n_mode' => 'prefixLangTitle',
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_equipment",
"config" => Array (
"type" => "input",
"size" => "30",
"eval" => "required",
)
),
'image' => array (
'exclude' => 0,
'l10n_mode' => 'exclude',
'label' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_image',
'config' => array (
'type' => 'group',
'internal_type' => 'file',
'allowed' => $GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'],
'max_size' => $GLOBALS['TYPO3_CONF_VARS']['BE']['maxFileSize'],
'uploadfolder' => 'uploads/tx_ttnews',
'show_thumbs' => '1',
'size' => 1,
'minitems' => 0,
'maxitems' => 1,
)
),
"exercises" => Array (
"exclude" => 1,
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_exercises",
"config" => Array (
"type" => "inline",
"foreign_table" => "tx_fitness_exercise2equipment",
"foreign_field" => "equipmentid",
"foreign_sortby" => "equipmentsort",
"foreign_label" => "exerciseid",
"maxitems" => 10,
'appearance' => array(
'showSynchronizationLink' => 1,
'showAllLocalizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showRemovedLocalizationRecords' => 1,
),
'behaviour' => array(
'localizationMode' => 'select',
),
)
),
),
"types" => Array (
"0" => Array("showitem" => "sys_language_uid;;;;1-1-1, l18n_parent, l18n_diffsource, hidden;;1, title;;;;2-2-2, image")
),
"palettes" => Array (
"1" => Array("showitem" => "")
)
);
Как результат, в админке мы увидим, что можно добавлять новые записи:
а при редактировании упражнений интерфейс будет таким:
Все супер, но не супер. Есть одно неудобство. Чтобы к упражнению можно было привязать несколько тренажеров, для этого, в первую очередь, необходимо предварительно создать записи этих тренажеров, т.е. для этого нужно каждый раз выходить из формы ввода упражнений (tt_news). Поэтому, я пришел к выводу, что нужно научиться вводить дочерние записи прямо из родительской таблицы. Технология Inline Relational Record Editing (IRRE) позволяет разработчику сделать это.
Дополнительное IRRE поле
К упражнениям можно привязать еще одну характеристику - группы мышц, которые оно разрабатывает. Как и в предыдущем случае, создаем дополнительно поле в tt_news - musclegroups, дочернюю таблицу - tx_fitness_musclegroup и связующую таблицу - tx_fitness_exercise2musclegroup.
CREATE TABLE tt_news (
...
musclegroups int(11) NOT NULL default '0',
...
);
CREATE TABLE tx_fitness_musclegroup (
uid int(11) NOT NULL auto_increment,
pid int(11) NOT NULL default '0',
tstamp int(11) NOT NULL default '0',
crdate int(11) NOT NULL default '0',
cruser_id int(11) NOT NULL default '0',
sys_language_uid int(11) NOT NULL default '0',
l18n_parent int(11) NOT NULL default '0',
l18n_diffsource mediumblob NOT NULL,
sorting int(10) NOT NULL default '0',
deleted tinyint(4) NOT NULL default '0',
hidden tinyint(4) NOT NULL default '0',
t3ver_oid int(11) NOT NULL default '0',
t3ver_id int(11) NOT NULL default '0',
t3ver_wsid int(11) NOT NULL default '0',
t3ver_label varchar(30) NOT NULL default '',
t3ver_state tinyint(4) NOT NULL default '0',
t3ver_stage tinyint(4) NOT NULL default '0',
t3ver_count int(11) NOT NULL default '0',
t3ver_tstamp int(11) NOT NULL default '0',
t3ver_move_id int(11) NOT NULL default '0',
t3_origuid int(11) NOT NULL default '0',
title tinytext NOT NULL,
exercises int(11) NOT NULL default '0',
PRIMARY KEY (uid),
KEY parent (pid)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8
CREATE TABLE `tx_fitness_exercise2musclegroup` (
`uid` int(11) NOT NULL auto_increment,
`pid` int(11) NOT NULL default '0',
`tstamp` int(11) NOT NULL default '0',
`crdate` int(11) NOT NULL default '0',
`cruser_id` int(11) NOT NULL default '0',
`sys_language_uid` int(11) NOT NULL default '0',
`l18n_parent` int(11) NOT NULL default '0',
`l18n_diffsource` mediumblob NOT NULL,
`deleted` tinyint(4) NOT NULL default '0',
`hidden` tinyint(4) NOT NULL default '0',
`t3ver_oid` int(11) NOT NULL default '0',
`t3ver_id` int(11) NOT NULL default '0',
`t3ver_wsid` int(11) NOT NULL default '0',
`t3ver_label` varchar(30) NOT NULL default '',
`t3ver_state` tinyint(4) NOT NULL default '0',
`t3ver_stage` tinyint(4) NOT NULL default '0',
`t3ver_count` int(11) NOT NULL default '0',
`t3ver_tstamp` int(11) NOT NULL default '0',
`t3ver_move_id` int(11) NOT NULL default '0',
`t3_origuid` int(11) NOT NULL default '0',
`exerciseid` int(11) NOT NULL default '0',
`musclegroupid` int(11) NOT NULL default '0',
`exercisesort` int(10) NOT NULL default '0',
`musclegroupsort` int(10) NOT NULL default '0',
PRIMARY KEY (`uid`),
KEY `parent` (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8
Строки для ext_tables.php:
'musclegroups' => Array (
"exclude" => 1,
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_secondarymusclegroups",
"config" => Array (
"type" => "inline",
"foreign_table" => "tx_fitness_exercise2musclegroup",
"foreign_field" => "exerciseid",
"foreign_sortby" => "exercisesort",
"foreign_label" => "musclegroupid",
/*"symmetric_field" => "exerciseid",
"symmetric_label" => "type",*/
"maxitems" => 10,
'appearance' => array(
'showSynchronizationLink' => 1,
'showAllLocalizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showRemovedLocalizationRecords' => 1,
'useSortable' => 1,
'collapseAll' => 1,
'expandSingle' => 1,
),
'behaviour' => array(
'localizationMode' => 'select',
),
)
),
t3lib_extMgm::allowTableOnStandardPages("tx_fitness_musclegroup");
$TCA["tx_fitness_musclegroup"] = Array (
"ctrl" => Array (
'title' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_musclegroup',
'label' => 'title',
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l18n_parent',
'transOrigDiffSourceField' => 'l18n_diffsource',
"sortby" => "sorting",
"delete" => "deleted",
"enablecolumns" => Array (
"disabled" => "hidden",
),
//"dynamicConfigFile" => t3lib_extMgm::extPath($_EXTKEY)."tca.mnasym.php",
"iconfile" => t3lib_extMgm::extRelPath($_EXTKEY)."res/hand.gif",
'versioningWS' => TRUE,
'origUid' => 't3_origuid',
),
"interface" => Array (
"showRecordFieldList" => "sys_language_uid,l18n_parent,l18n_diffsource,hidden,title,exercises"
),
//"feInterface" => Array (
// "fe_admin_fieldList" => "sys_language_uid, l18n_parent, l18n_diffsource, hidden, title, exercises",
//)
"feInterface" => $TCA["tx_fitness_musclegroup"]["feInterface"],
"columns" => Array (
'sys_language_uid' => array (
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.language',
'config' => array (
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
)
)
),
'l18n_parent' => array (
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.l18n_parent',
'config' => array (
'type' => 'select',
'items' => array (
array('', 0),
),
'foreign_table' => 'tx_fitness_bodypart',
'foreign_table_where' => 'AND tx_fitness_musclegroup.pid=###CURRENT_PID### AND tx_fitness_musclegroup.sys_language_uid IN (-1,0)',
)
),
'l18n_diffsource' => array (
'config' => array (
'type' => 'passthrough'
)
),
"hidden" => Array (
"exclude" => 1,
"label" => "LLL:EXT:lang/locallang_general.xml:LGL.hidden",
"config" => Array (
"type" => "check",
"default" => "0"
)
),
"title" => Array (
"exclude" => 1,
'l10n_mode' => 'prefixLangTitle',
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_musclegroup",
"config" => Array (
"type" => "input",
"size" => "30",
"eval" => "required",
)
),
"exercises" => Array (
"exclude" => 1,
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_exercises",
"config" => Array (
"type" => "inline",
"foreign_table" => "tx_fitness_exercise2musclegroup",
"foreign_field" => "musclegroupid",
"foreign_sortby" => "musclegroupsort",
"foreign_label" => "exerciseid",
"maxitems" => 10,
'appearance' => array(
'showSynchronizationLink' => 1,
'showAllLocalizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showRemovedLocalizationRecords' => 1,
),
'behaviour' => array(
'localizationMode' => 'select',
),
)
),
),
"types" => Array (
"0" => Array("showitem" => "sys_language_uid;;;;1-1-1, l18n_parent, l18n_diffsource, hidden;;1, title;;;;2-2-2, exercises")
),
"palettes" => Array (
"1" => Array("showitem" => "")
)
);
t3lib_extMgm::allowTableOnStandardPages("tx_fitness_exercise2musclegroup");
$TCA["tx_fitness_exercise2musclegroup"] = Array (
"ctrl" => Array (
'title' => 'LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_exercise2musclegroup',
'label' => 'exerciseid',
'label_alt' => 'musclegroupid',
'label_alt_force' => TRUE,
'tstamp' => 'tstamp',
'crdate' => 'crdate',
'cruser_id' => 'cruser_id',
'languageField' => 'sys_language_uid',
'transOrigPointerField' => 'l18n_parent',
'transOrigDiffSourceField' => 'l18n_diffsource',
"delete" => "deleted",
"enablecolumns" => Array (
"disabled" => "hidden",
),
"iconfile" => t3lib_extMgm::extRelPath($_EXTKEY)."res/finger-bw.gif",
'versioningWS' => TRUE,
'origUid' => 't3_origuid',
'shadowColumnsForNewPlaceholders' => 'exerciseid, musclegroupid',
),
);
$TCA["tx_fitness_exercise2musclegroup"] = Array (
"ctrl" => $TCA["tx_fitness_exercise2musclegroup"]["ctrl"],
"interface" => Array (
"showRecordFieldList" => "sys_language_uid,l18n_parent,l18n_diffsource,hidden,exerciseid,musclegroupid,exercisesort,musclegroupsort,type"
),
"feInterface" => $TCA["tx_fitness_exercise2musclegroup"]["feInterface"],
"columns" => Array (
'sys_language_uid' => array (
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.language',
'config' => array (
'type' => 'select',
'foreign_table' => 'sys_language',
'foreign_table_where' => 'ORDER BY sys_language.title',
'items' => array(
array('LLL:EXT:lang/locallang_general.xml:LGL.allLanguages', -1),
array('LLL:EXT:lang/locallang_general.xml:LGL.default_value', 0)
)
)
),
'l18n_parent' => array (
'displayCond' => 'FIELD:sys_language_uid:>:0',
'exclude' => 1,
'label' => 'LLL:EXT:lang/locallang_general.xml:LGL.l18n_parent',
'config' => array (
'type' => 'select',
'items' => array (
array('', 0),
),
'foreign_table' => 'tx_fitness_exercise2musclegroup',
'foreign_table_where' => 'AND tx_fitness_exercise2musclegroup.pid=###CURRENT_PID### AND tx_fitness_exercise2musclegroup.sys_language_uid IN (-1,0)',
)
),
'l18n_diffsource' => array (
'config' => array (
'type' => 'passthrough'
)
),
"hidden" => Array (
"exclude" => 1,
"label" => "LLL:EXT:lang/locallang_general.xml:LGL.hidden",
"config" => Array (
"type" => "check",
"default" => "0"
)
),
"exerciseid" => Array (
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_exercise",
"config" => Array (
"type" => "select",
"foreign_table" => "tt_news",
'foreign_table_where' => 'AND type=3',
"maxitems" => 1,
'localizeReferences' => 1,
)
),
"musclegroupid" => Array (
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_musclegroup",
"config" => Array (
"type" => "select",
"foreign_table" => "tx_fitness_musclegroup",
"maxitems" => 1,
'localizeReferences' => 1,
)
),
"exercisesort" => Array (
"config" => Array (
"type" => "passthrough",
)
),
"musclegroupsort" => Array (
"config" => Array (
"type" => "passthrough",
)
),
/*"type" => Array (
"exclude" => 0,
"label" => "LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.tx_ttnewsfield_musclegroup_type",
'config' => array(
'type' => 'select',
'items' => array(
array('LLL:EXT:ttnews_fitness/locallang_db.xml:musclegroup_type.1', 'Primary'),
array('LLL:EXT:ttnews_fitness/locallang_db.xml:musclegroup_type.2', 'Secondary'),
),
),
),*/
),
"types" => Array (
"0" => Array("showitem" => "sys_language_uid;;;;1-1-1, l18n_parent, l18n_diffsource, hidden;;1, title;;;;2-2-2, exerciseid;;;;3-3-3, musclegroupid, exercisesort, musclegroupsort")
),
"palettes" => Array (
"1" => Array("showitem" => "")
)
);
Получаем следующий результат в BE:
Как видим, такая форма более удобна, т.к. позволяет создавать дочерние записи прямо внутри родительской. Больше информации о IRRE можно найти здесь.
Нужно сказать, что после добавления всех вышеуказанных изменений в файле ext_tables.php, форма ввода tt_news содержать новых полей не будет. Для этого нужно добавить еще 2 строки:
t3lib_div::loadTCA("tt_news");
t3lib_extMgm::addTCAcolumns("tt_news",$fitnessColumns,1);
Возможно у кого-то возникнет вопрос: "А нафига мне Новости с кучей всяких дополнительных полей, которые нужны в одном случае, а в другом уже не нужны?". Все можно настроить. Для того, чтобы стандартные новости не содержали лишних полей создается дополнительный индивидуально настроенный тип записи. Изначально новости имеют 3 типа записей: Новости, Статьи, Внешняя ссылка. Создать еще один тип - проще простого. В файл ext_tables.php своего расширения добавляем:
$GLOBALS['TCA']['tt_news']['columns']['type']['config']['items'][] = Array('LLL:EXT:ttnews_fitness/locallang_db.xml:tt_news.type.I.3', 3);
$GLOBALS['TCA']['tt_news']['ctrl']['typeicons']['3'] = t3lib_extMgm::extRelPath($_EXTKEY)."res/ball-ico.gif";
Что дали последние 2 строки? Первое, добавили новый тип записи к новостям с кодом 3. Текстовое название этого типа сидит в файле locallang_db.xml в строке:
<label index="tt_news.type.I.3">Exercise</label>
Второе, новому типу записей сопоставлена иконка, которая сидит в каталоге res нашего расширения с названием - ball-ico.gif (16 на 16 пикселей).
А для того, чтобы новые поля в "новых новостях" были размещены в нужном и удобном для пользователя порядке добавляются такие строки:
$GLOBALS['TCA']['tt_news']['types']['3']['showitem'] = 'hidden, type;;;;1-1-1,title;;;;2-2-2,tx_fitness_shared_office_suitability,tx_fitness_workarea,bodytext;;2;richtext:rte_transform[flag=rte_enabled|mode=ts];4-4-4,tx_fitness_how2;;2;richtext:rte_transform[flag=rte_enabled|mode=ts];4-4-4,
--div--;LLL:EXT:ttnews_fitness/locallang_db.xml:exercise_info.name,tx_fitness_easier;;2;richtext:rte_transform[flag=rte_enabled|mode=ts];4-4-4,tx_fitness_harder;;2;richtext:rte_transform[flag=rte_enabled|mode=ts];4-4-4,tx_fitness_hints;;2;richtext:rte_transform[flag=rte_enabled|mode=ts];4-4-4,
--div--;LLL:EXT:ttnews_fitness/locallang_db.xml:exercise_relations, category;;;;3-3-3,tx_fitness_purpose,tx_fitness_equipment,tx_fitness_equivalent_gym_equipment,mainmusclegroups,musclegroups,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.media, tx_damnews_dam_images,tx_fitness_musclegroupimage,tx_fitness_vimeo;;;;1-1-1,
--div--;LLL:EXT:tt_news/locallang_tca.xml:tt_news.tabs.access, starttime,endtime,fe_group,editlock';
Полный текст файла ext_tables.php можно взять здесь.
P.S. Это не статья, а по объему уже "Война и Мир"...:)
Подписаться на:
Сообщения (Atom)
О себе

- Вадим Гиркало
- Фрилансер, веб-разработчик сайтов на базе бесплатной, мощнейшей и очень гибкой CMS системы - TYPO3.
Мой сайт
Позвонить мне в Skype
TOP - 3
-
Как я уже писал в одной своей заметке ( SEO и общие рекомендации ), для сайта очень важно, чтобы при обращении к заведомо несуществующей ст...
-
Дорабатывая очередной свой сайт столкнулся с такой проблемкой. В шапке сайта есть две флэш вставки - банер, который вставлен через конструкц...
-
Несмотря на то, что материала по данной тематике вроде бы и достаточно, но весь он носит кусочно-латочно-разрозненный характер, что мешает б...