В качестве значения свойства иметь картинку с превью.
Это могут быть например фотки гостиницы на туристическом сайте или что-то подобное.
[spoiler]
Одно из предложений прозвучало так: хранить изображения в отдельном инфоблоке и показывать в компоненте связанные элементы.
Вот что удалось сделать за 1 1/2 часа на :
AddEventHandler("iblock", "OnIBlockPropertyBuildList", array("CIBlockPropertyPicture", "GetUserTypeDescription"));
AddEventHandler("iblock", "OnBeforeIBlockElementDelete", array("CIBlockPropertyPicture", "OnBeforeIBlockElementDelete"));
class CIBlockPropertyPicture
{
function GetUserTypeDescription()
{
return array(
"PROPERTY_TYPE" =>"E",
"USER_TYPE" =>"Picture",
"DESCRIPTION" =>"Картинка",
"GetPropertyFieldHtml" =>array("CIBlockPropertyPicture", "GetPropertyFieldHtml"),
"GetPublicViewHTML" =>array("CIBlockPropertyPicture", "GetPublicViewHTML"),
"ConvertToDB" =>array("CIBlockPropertyPicture", "ConvertToDB"),
//"GetPublicEditHTML" =>array("CIBlockPropertyPicture","GetPublicEditHTML"),
//"GetAdminListViewHTML" =>array("CIBlockPropertyPicture","GetAdminListViewHTML"),
//"CheckFields" =>array("CIBlockPropertyPicture","CheckFields"),
//"ConvertFromDB" =>array("CIBlockPropertyPicture","ConvertFromDB"),
//"GetLength" =>array("CIBlockPropertyPicture","GetLength"),
);
}
function GetPropertyFieldHtml($arProperty, $value, $strHTMLControlName)
{
$LINK_IBLOCK_ID = intval($arProperty["LINK_IBLOCK_ID"]);
if($LINK_IBLOCK_ID)
{
$ELEMENT_ID = intval($value["VALUE"]);
if($ELEMENT_ID)
{
$rsElement = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $arProperty["LINK_IBLOCK_ID"], "ID" => $value["VALUE"]), false, false, array("ID", "PREVIEW_PICTURE", "DETAIL_PICTURE"));
$arElement = $rsElement->Fetch();
if(is_array($arElement))
$file_id = $arElement["DETAIL_PICTURE"];
else
$file_id = 0;
}
else
{
$file_id = 0;
}
if($file_id)
{
$db_img = CFile::GetByID($file_id);
$db_img_arr = $db_img->Fetch();
if($db_img_arr)
{
$strImageStorePath = COption::GetOptionString("main", "upload_dir", "upload");
$sImagePath = "/".$strImageStorePath."/".$db_img_arr["SUBDIR"]."/".$db_img_arr["FILE_NAME"];
return '<label><input name="'.$strHTMLControlName["VALUE"].'[del]" value="Y" type="checkbox"> Удалить файл '.$sImagePath.'</label>'
.'<input name="'.$strHTMLControlName["VALUE"].'[old]" value="'.$ELEMENT_ID.'" type="hidden">';
}
}
return '<input type="file" size="'.$arProperty["COL_COUNT"].'" name="'.$strHTMLControlName["VALUE"].'"/>';
}
else
{
return "Ошибка настройки свойства. Укажите инфоблок в котором будут храниться картинки.";
}
}
function GetPublicViewHTML($arProperty, $value, $strHTMLControlName)
{
$LINK_IBLOCK_ID = intval($arProperty["LINK_IBLOCK_ID"]);
if($LINK_IBLOCK_ID)
{
$ELEMENT_ID = intval($value["VALUE"]);
if($ELEMENT_ID)
{
$rsElement = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $arProperty["LINK_IBLOCK_ID"], "ID" => $value["VALUE"]), false, false, array("ID", "PREVIEW_PICTURE", "DETAIL_PICTURE"));
$arElement = $rsElement->Fetch();
if(is_array($arElement))
return CFile::Show2Images($arElement["PREVIEW_PICTURE"], $arElement["DETAIL_PICTURE"]);
}
}
return "";
}
function ConvertToDB($arProperty, $value)
{
$arResult = array("VALUE" => "", "DESCRIPTION" => "");
$LINK_IBLOCK_ID = intval($arProperty["LINK_IBLOCK_ID"]);
if($LINK_IBLOCK_ID)
{
if(
is_array($value["VALUE"])
&& is_array($value["VALUE"]["error"])
&& $value["VALUE"]["error"]["VALUE"] == 0
&& $value["VALUE"]["size"]["VALUE"] > 0
)
{
$arDetailPicture = array(
"name" => $value["VALUE"]["name"]["VALUE"],
"type" => $value["VALUE"]["type"]["VALUE"],
"tmp_name" => $value["VALUE"]["tmp_name"]["VALUE"],
"error" => $value["VALUE"]["error"]["VALUE"],
"size" => $value["VALUE"]["size"]["VALUE"],
);
$obElement = new CIBlockElement;
$arResult["VALUE"] = $obElement->Add(array(
"IBLOCK_ID" => $LINK_IBLOCK_ID,
"NAME" => $arDetailPicture["name"],
"DETAIL_PICTURE" => $arDetailPicture,
), false, false, true);
}
elseif(
is_array($value["VALUE"])
&& isset($value["VALUE"]["size"])
&& !is_array($value["VALUE"]["size"])
&& $value["VALUE"]["size"] > 0
)
{
$arDetailPicture = array(
"name" => $value["VALUE"]["name"],
"type" => $value["VALUE"]["type"],
"tmp_name" => $value["VALUE"]["tmp_name"],
"error" => intval($value["VALUE"]["error"]),
"size" => $value["VALUE"]["size"],
);
$obElement = new CIBlockElement;
$arResult["VALUE"] = $obElement->Add(array(
"IBLOCK_ID" => $LINK_IBLOCK_ID,
"NAME" => $arDetailPicture["name"],
"DETAIL_PICTURE" => $arDetailPicture,
), false, false, true);
}
elseif($value["VALUE"]["del"])
{
$obElement = new CIBlockElement;
$obElement->Delete($value["VALUE"]["old"]);
}
elseif($value["VALUE"]["old"])
{
$arResult["VALUE"] = $value["VALUE"]["old"];
}
elseif(!is_array($value["VALUE"]) && intval($value["VALUE"]))
{
$arResult["VALUE"] = $value["VALUE"];
}
}
return $arResult;
}
function OnBeforeIBlockElementDelete($ELEMENT_ID)
{
$arProperties = array();
$rsElement = CIBlockElement::GetList(array(), array("ID" => $ELEMENT_ID), false, false, array("ID", "IBLOCK_ID"));
$arElement = $rsElement->Fetch();
if($arElement)
{
$rsProperties = CIBlockProperty::GetList(array(), array("IBLOCK_ID" => $arElement["IBLOCK_ID"], "USER_TYPE" => "Picture"));
while($arProperty = $rsProperties->Fetch())
$arProperties[] = $arProperty;
}
$arElements = array();
foreach($arProperties as $arProperty)
{
$rsPropValues = CIBlockElement::GetProperty($arElement["IBLOCK_ID"], $arElement["ID"], array(
"EMPTY" => "N",
"ID" => $arProperty["ID"],
));
while($arPropValue = $rsPropValues->Fetch())
{
$ID = intval($arPropValue["VALUE"]);
if($ID > 0)
$arElements[$ID] = $ID;
}
}
foreach($arElements as $to_delete)
{
CIBlockElement::Delete($to_delete);
}
}
}
|
Что мы в итоге имеем:
1. Интерфейс редактирования элемента с возможностью добавления и удаления изображений.
2. При удалении элемента связанная с ним информация удаляется.
3. Поддержка компонент публичной части.
Инструкция по применению:
1. Этот код надо разместить в файле /bitrix/php_interface/init.php
2. Создать инфоблок для хранения изображений и в его настройках указать параметры генерации картинки предварительного просмотра из детальной (на вкладке "поля").
3. В инфоблоке "гостинницы" добавить свойство типа "Картинка" и в доп. настроках этого свойства указать созданный на первом шаге инфоблок. Не забудьте указать символьный код свойства.
4. Создать элемент и "поиграться" со значениям этого свойства.
5. В публичной части например в компоненте news в параметрах настройки списка элементов выбрать это свойство.
6. Пойти выпить кофе.
PS предлагаю дополнить и развить этот код с целью будущего включения в поставку продукта.
все отлично работает, мне как раз для доски объявлений и автосалона, где много фото в детальном.
а, например, в доске объявлений простому пользователю при подаче объявления это не доступно, название свойства появилось, а возможность загрузить фото - нет. Подскажите, что дополнительно надо сделать.
Fatal error: Cannot use string offset as an array in /var/www/bitrix/php_interface/init.php on line 679
Да, классно придумано, а главное удобно.
По самому подходу решения задачи выскажу свои против:
1. Создавать заранее тумбнейлы непрактично. Понимаешь это при первом же редизайне, когда картинок очень много и нужны другие размеры. Куда удобнее их создавать по месту, как это делается в блогах.
2. Организация хранения такого рода тумбнейлов в отдельных инфоблоках а) нерационально, б) требует лишних телодвижений (создать отдельный инфоблок).
3. Использован тип юзертайпа E (элемент), хотя фактически это файлы (F). Не исключено, что это вызовет дополнительные трудности. Например, для вывода в шаблоне всех связей с элементами, появляется дополнитльное условие "или", и теоретически это "или" появляется автоматом у всех.
4. Типоразмеров для тумбнейлов картинки бывает больше одного. И по моему скромному опыту, обычно нужно три. Т.е. негде хранить дополнительные изображения, а подключать сюда еще и свойства это уже чересчур.
5. Тумбнейлы бывают разных типов. Например, должны быть железно указанных размеров, и не важно прямоугольной или квадратной формы источник. Т.е. штатные средства ресайзинга в инфоблоках не подойдут. Ну, и ватремарки, ручное/визуальное масштабирование, рамки и многое многое другое.
В общем, если нужны обычные тумбнейлы (без сложных текстовых описаний, сортировок, участием в поиске и т.п.), то лучше просто загружать в обычное свойство файл большие картинки и уменьшать их как требуется в дизайне по месту вывода. Естественно, с сохранением результата на диск. Правда этот способ тоже не очень хорош, если на списочных страницах много элементов с большим количеством картинок и оригиналы очень большие - первая генерация страницы будет очень долгой, а на всяких "мастерхостах" может привести и к ауту.
Но причина написания комментария не в анализе подхода.
Я хотел бы поинтересоваться у Максима Смринова, почему был использован именно тип E, а не логичный для задачи тип F?
Вернее, догадываюсь почему, и в очередной раз бы молча прошел мимо, но здесь автор поста сам разработчик модуля инфоблоков, человек, у которого есть ключи от запертой двери.
В общем для себя и для других интересующихся хотел бы уточнить, тип E выбран потому что для типа F негде хранить настройки ресайзинга, и вообще сейчас нельзя для всех типов, кроме типа S, задать хоть какие-то кастомные настройки?
Если я прав, то сколько еще будет продолжаться такая ситуация? Не лучше ли довести до ума интерфейсы юзертайпов и раскрыть всех их потенциал? А потенциал там просто огромен.
Или в очередной раз таким вот примером вы показываете как все прекрасно и гибко, а партнеры не понятно чего ноют? Тогда пытаясь доказать, что это не так и параллельно отвечая на Ваше предложение дополнить и развить код с целью будущего включения в поставку внесу свои предложения:
- главное: перевести на тип F
- расширение функционала: добавить возможность для одной картинки делать несколько миниатюр
- расширение функционала: добавить возможность сортировки картинок и добавить поле для текствого описания
Создавать заранее тумбнейлы непрактично. Понимаешь это при первом же редизайне, когда картинок очень много и нужны другие размеры. Куда удобнее их создавать по месту, как это делается в блогах.
Можно пройтись скриптом и пережать заново, для других размеров. Делается один раз в пол года, тогда когда меняется дизайн.
Мне кажется что с автоматическим ресайзингом гемороя больше.
Например, если автообжималка, где в качестве параметра указывается размер:
тогда злоумышленник может положить сервер запросами этой картинки с разными размерами.
Например, если автообжималка, где в качестве параметра указывается размер:
Мне кажется что с автоматическим ресайзингом гемороя больше.
Если есть возможность, то посмотрите функцию CSocNetTools::InitImage(), может быть она натолкнет вас на мысли.
Я не стал счастливым обладателем модуля социальных сетей.
А сами размеры передаем не через адресную строку, а задаем прямо в компоненте или шаблоне.
Еще я немного не въеахал, эти картинки чистятся когда удаляешся кеш, или они постоянно скапливаются в папке upload?
"/".$uploadDirName."/resize_cache/"....
$uploadDirName - по умолчанию = /upload/
Я так понял что эта функция работает только для рисунков, которые хранятся в базе:
if (!is_array($file) && IntVal($file) > 0) { $dbRes = CFile::GetByID(IntVal($file)); $file = $dbRes->Fetch(); } if (!is_array($file) || !array_key_exists("FILE_NAME", $file) || StrLen($file["FILE_NAME"]) <= 0) return false;И файл сохраняется в
Может есть надежда, что когда удаляется элемент инфоблока, то удаляются и другие его картинки, которые хранятся в $file["SUBDIR"] ?
Пока я вижу что с таким подходом через пол года папка resize_cache хорошо распухнет, если, конечно, не повесить её автоочистку раз в месяц (И в это день сервер может лечь, пока перегенерит все картинки для всего сайта).
Сам подоход очень интересный, пожалуй, теперь во всех проектах буду использовать его.
Вот только с кешем кривовато получается.
Почему?
Если доп. картинки автоматом удаляются при удалении основного - то тогда проблем никаких.
Если не удалось посмотреть, то скажу вам, файлы удаляются при удалении основного.
Интересно, где вы это нашли? посмотрел фукнции CIblockElement::Delete() и CFile::Delete(), там не видно чтобы что-то удалялось из папки resize_cache.
Конечно все реализовано с большими костылями. Многое в работающей системе не устраивает. Так например хочется научить визуальный редактор на лету отображать картинки по вышеописаной схеме. Еще хочется в Битриксе расширить функционал для доп. свойств. Так например для привязки различных элементов к региону сделали ИБ с деревом регионов, а в свойствах элемента доп. поле с привязкой к разделу. Теперь чтобы например получить все новости из Федерального округа, нужно сначала перелопатить ИБ "Регионы" на предмет вложенных разделов, а потом искать в ИБ "Новости" по доп. свойству привзки к региону. Зато для своего ИБ - INCLUDE_SUBSECTIONS и все.
А с фотками вообще хотел реализовать штуку: льешь исходник в любом формате, а в папочке tmp создаются превьюшки нужных размеров с определенным временем жизни. Если долго их никто не смотрит они умирают, при повторном обращении создаются.
Почему-то в фотогалерее не реализовали работу с ICMP инфой из фоток. Да и форматов могли поболе сделать.
Вот. Наболело. Извините что возможны ламерские рассуждения, но я не так давно полез в Битрикс, с кризисом приходится осваивать новые профессии
В компонентах которые выводят вские вещи вроде связанных картинок и файлов (скриншоты программ, демонстрации и прочее) происходит следующее:
1 - получили для свойства типа F массив ID'ентификаторов файлов (обычно на один элемент ИБ может быть от 1 до 10 файлов: презентации, документы и.т.д).
Потом в цикле обходим его и вызываем CFile::GetFileArray или CFile::GetByID.
Почему бы не передавать массив идентификаторов? Тогда был бы один запрос к БД. Да, я понимаю что в GetByID используется CACHE_MANAGER и не каждый запрос к файлу порождает SQL-запрос.
Я сейчас посмотрел в модуле main в классе CAllFile появилась функция GetList
Судя по коду - это то о чём я спрашиваю. В . Можно ей пользоваться?
Т.е. если передать строкой, то всё ОК
$arFilesID = array("@ID" => '38078, 38080');
Странно как то, приходится конверить массив перед передачей в функцию.
Это так задумано?
$rcsFiles = CFile::GetList(false, $arFilesID, false);
И @ID в плейсхолдере сборщика запросов. Это тоже что то новое для пользовательского API
1 - $arOrder = Array(), - в коде жёстко задана сортировка
"FROM b_file f ".
$strSqlSearch." ".
"ORDER BY f.ID ASC";
3 - $arParams = Array() - в теле функции его нет вообше похоже.
Состав полей возвращаемых CFile::GetFileArray и CFile::GetList различается.
CFile::GetFileArray добавляет ещё поле SRC, осуществляя сборку полного пути до этого файла с учётом наличия константы BX_IMG_SERVER.
$src = "/".(COption::GetOptionString("main", "upload_dir", "upload"))."/".$arFile["SUBDIR"]."/".$arFile["FILE_NAME"];
$src = str_replace("//","/",$src);
if(defined("BX_IMG_SERVER"))
$src = BX_IMG_SERVER.$src;
$arReturn = $arFile + Array("SRC" => $src);
CFile::GetList не осуществляет этого возвращая просто объект CDBResult
Как устаканится, думаю нужно будет написать в документации, что бы не позабыли это сделать тогда сами.
Хотя да, думаю каждый кто использует CFile::GetList напишет свою обёртку, что бы возвращать массивы уже, а не объект и фетчить его.
Константа BX_IMG_SERVER используется если все ресурсы хранятся на другом сервере?
в доках про него ничего
доб.: наврал про побитые, но имен нету
Но есть 2 замечания. Для того чтобы она правильно отработала нужно явно указать высоту и ширину:
У меня так и не получилось обжать картинку до ширины 100 пикселей, а чтобы высота вычислась автоматически пропорционально.
В дизайне обычно такие картинки имеют либо одинаковую ширину, либо одинаковую высоту. И реже нужно чтобы была заданная и высота и ширина.
Потом, рисунки jpg обжимаются в ужасном качестве, с заметным муаром. Так как по умолчанию качество стоит 75, а нужно 100.
На сервере библиотека GD последней версии.
А так функция действительно очень полезная, хорошо бы её включить в документацию. Обжатие происходит довольно быстро, у меня на сервере 10 картинок с размером 400х400 обжимаются до размера 100х100 за 0,2 сек. Так как это делается только один раз при первой генерации страницы, то выгода очевидна.
Ну, напишите свою функцию - быстрее и надежнее будет, и под ваши требования. Будут дорабатывать штатную или нет - вопрос весьма спорный. Для информации (и смешно и грустно становится), почти идентичный функционал обработки картинок присутсвует в пяти модулях: в блогах, в инфоблоках, в главном модуле, в фотогалерее и в соц.сетях. В общем, каждый разработчик модуля пишет данный функционал под себя. Вот такой вот фреймворк получается...
это называется с пылесоса делать ракету
elseif( is_array($value["VALUE"]) && isset($value["VALUE"]["size"]) && !is_array($value["VALUE"]["size"]) && $value["VALUE"]["size"] > 0 ) { $arDetailPicture = array( "name" => $value["VALUE"]["name"], "type" => $value["VALUE"]["type"], "tmp_name" => $value["VALUE"]["tmp_name"], "error" => intval($value["VALUE"]["error"]), "size" => $value["VALUE"]["size"], ); $obElement = new CIBlockElement; $arResult["VALUE"] = $obElement->Add(array( "IBLOCK_ID" => $LINK_IBLOCK_ID, "NAME" => $arDetailPicture["name"], "DETAIL_PICTURE" => $arDetailPicture, ), false, false, true); }в чем может быть причина?
Собираюсь использовать в нескольких проектах - не охота обновлять данный "хак"
init.php не обновляется. Этот файл специально для таких случаев.
Попробовал. Просто отлично! То что нужно.
Но вот как бы этим фоткам еще и заголовок при загрузке прописывать? Куда?
Элементы по умолчанию получают название картинки типа IMG1236.jpg - дословно, из названия файла...
Что-то типа принудительного "называния" элементов инфоблока с картинками не помешало бы.
Где бы это "подкрутить"?
$rsElement = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $arProperty["LINK_IBLOCK_ID"], "ID" => $value["VALUE"]), false, false, array("ID", "PREVIEW_PICTURE", "DETAIL_PICTURE"));В
В методе ConvertToDB передать в NAME соотв. значение из формы. Не забываем, что это поле обязательное и не может быть пустым. Поэтому надо предусмотреть "дефолтное" значение.
Все.
Мне никак не удается в шаблоне получить отдельно значения пути к картинке, детальной картинке и их дескрипшену. По умолчанию выводится что-то наподобие
<a title="Увеличить" onclick="ImgShw('/upload/iblock/.../*.jpg','','', ''); return false;" href="/upload/iblock/.../*.jpg" target=_blank><img src="/upload/iblock/.../*.jpg" border="0" alt="" width=* height=* /></a>CFile::GetPath, который выручал в большинстве случаев, тут, ясно, не помогает... Чем воспользоваться? CFile::GetFileArray ?
Пока просто вывожу и кое-как размещаю стилями, но это же не выход:
<?foreach($arResult['DISPLAY_PROPERTIES']['GALLERY']['DISPLAY_VALUE'] as $value) { echo($value); }?>CIBlockElement::GetList(array("SORT"=>"ASC",array("ID"=>$value),false,false,array("ID", "NAME", "DETAIL_PICTURE", "PREVIEW_PICTURE") + Fetch и будет счастье.
Понимаю, что и так разжевали по самое не могу, но - пожалуйста - еще раз - последний - хоть чуть поподробнее. Дальше уж возможно разберусь.
Или подскажите где формируется код
<a title="Увеличить" onclick="ImgShw('/upload/iblock/.../*.jpg','','', ''); return false;" href="/upload/iblock/.../*.jpg" target=_blank><img src="/upload/iblock/.../*.jpg" border="0" alt="" width=* height=* /></a>Я правильно понял, то есть писать свое свойство?
проверку ID свойства. Иначе удаляются не только связные картинки, а вообще все связные элементы
Вам надо заняться отладкой.
$rsElement = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $arProperty["LINK_IBLOCK_ID"], "ID" => $value["VALUE"]), false, false, array("ID", "PREVIEW_PICTURE", "DETAIL_PICTURE", "NAME")); $arElement = $rsElement->Fetch(); if(is_array($arElement))$strImageStorePath = COption::GetOptionString("main", "upload_dir", "upload"); $sImagePath = "/".$strImageStorePath."/".$db_img_arr["SUBDIR"]."/".$db_img_arr["FILE_NAME"]; return '<label><input name="'.$strHTMLControlName["NAME"].'" value="Фото к новости" type="text"> <input name="'.$strHTMLControlName["VALUE"].'[del]" value="Y" type="checkbox"> Удалить файл '.$sImagePath.'</label>' .'<input name="'.$strHTMLControlName["VALUE"].'[old]" value="'.$ELEMENT_ID.'" type="hidden">';Уже на энном сайте использую этот ваш код, все всегда просто отлично.
Но, вот, проблема появилась:
на новом сайте периодически слетает привязка картинок к элементу.
Не удается уловить все закономерности, но одна выяснилась:
Привязка (в таблице b_iblock_element_property) совершенно точно слетает у элементов при массовом редактировании других свойств этих элементов прямо в списках инфоблока. Слетает только привязка у "элемента-родителя", все картинки остаются на своих местах... ну как-то так
Казалось бы, при чем здесь дополнительные картинки?
Разница с другими сайтами, на которых все ок, одна-единственная: все таблицы сайта в InnoDB, пока мне неясно важно это или нет.
Поможете? Кто как не автор может понять все подноготные своего кода?
- добавлена сортировка прямо в списке.
- добавлен вывод картинок в админке.
AddEventHandler("iblock", "OnIBlockPropertyBuildList", array("CIBlockPropertyPicture", "GetUserTypeDescription")); AddEventHandler("iblock", "OnBeforeIBlockElementDelete", array("CIBlockPropertyPicture", "OnBeforeIBlockElementDelete")); class CIBlockPropertyPicture { function GetUserTypeDescription() { return array( "PROPERTY_TYPE" =>"E", "USER_TYPE" =>"Picture", "DESCRIPTION" =>"Картинка", "GetPropertyFieldHtml" =>array("CIBlockPropertyPicture", "GetPropertyFieldHtml"), "GetPublicViewHTML" =>array("CIBlockPropertyPicture", "GetPublicViewHTML"), "ConvertToDB" =>array("CIBlockPropertyPicture", "ConvertToDB"), //"GetPublicEditHTML" =>array("CIBlockPropertyPicture","GetPublicEditHTML"), //"GetAdminListViewHTML" =>array("CIBlockPropertyPicture","GetAdminListViewHTML"), //"CheckFields" =>array("CIBlockPropertyPicture","CheckFields"), //"ConvertFromDB" =>array("CIBlockPropertyPicture","ConvertFromDB"), //"GetLength" =>array("CIBlockPropertyPicture","GetLength"), ); } function GetPropertyFieldHtml($arProperty, $value, $strHTMLControlName) { CJSCore::Init('jquery'); $LINK_IBLOCK_ID = intval($arProperty["LINK_IBLOCK_ID"]); if($LINK_IBLOCK_ID) { $ELEMENT_ID = intval($value["VALUE"]); if($ELEMENT_ID) { $rsElement = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $arProperty["LINK_IBLOCK_ID"], "ID" => $value["VALUE"]), false, false, array("ID", "PREVIEW_PICTURE", "DETAIL_PICTURE", 'SORT')); $arElement = $rsElement->Fetch(); if(is_array($arElement)) $file_id = $arElement["DETAIL_PICTURE"]; else $file_id = 0; } else { $file_id = 0; } if($file_id) { $db_img = CFile::GetByID($file_id); $db_img_arr = $db_img->Fetch(); if($db_img_arr) { $renderImage = CFile::ResizeImageGet($file_id, Array("width" => 200, "height" => 200)); $strImageStorePath = COption::GetOptionString("main", "upload_dir", "upload"); $sImagePath = "/".$strImageStorePath."/".$db_img_arr["SUBDIR"]."/".$db_img_arr["FILE_NAME"]; return '<div class="mpic_wrap"><label><input name="'.$strHTMLControlName["VALUE"].'[del]" value="Y" type="checkbox"> Удалить файл '.$sImagePath.'</label>' .'<input name="'.$strHTMLControlName["VALUE"].'[old]" value="'.$ELEMENT_ID.'" type="hidden">' .'<br><br><img style="float:left;margin-right:30px;" alt="" src="'.$renderImage['src'].'" />'.'<label>Порядок:<br><input class="sort" name="'.$strHTMLControlName["VALUE"].'[sort]" type="text" value="'.$arElement['SORT'].'" size="4" /></label>' .'<br><a target="_blank" href="/bitrix/admin/iblock_element_edit.php?IBLOCK_ID='.$LINK_IBLOCK_ID.'&type=content&ID='.$arElement['ID'].'&lang=ru&find_section_section=-1&WF=Y">' .'редактировать' .'</a><br>' .'<br style="clear:both;"><br><br></div>'; } } static $inc = false; $script = <<<HTML <script> function sortPics() { var parent = $($('.mpic_wrap').get(0)).closest('tbody') var arr = new Array(); $('.mpic_wrap').each(function(i){ arr[i] = $(this).closest('tr'); }); /* сортировка строк в массиве*/ for (var i=0; i<arr.length; i++) { for (var j=0; j<arr.length-i; j++) { sort1 = parseInt( $(arr[j]).find('.sort').val() ); sort2 = parseInt( $(arr[j+1]).find('.sort').val() ); if (sort1 > sort2) { var buf = arr[j]; arr[j] = arr[j+1]; arr[j+1] = buf; } } } for (var i=arr.length-1; i>=0; i--) { parent.prepend('<tr>'+$(arr[i]).html()+'</tr>'); $(arr[i]).remove(); } } $(document).ready(function(){ sortPics(); }); </script> HTML; $ret = '<input type="file" size="'.$arProperty["COL_COUNT"].'" name="'.$strHTMLControlName["VALUE"].'"/>'; if ($inc==false) { $ret = $script.$ret; $inc = true; } return $ret; } else { return "Ошибка настройки свойства. Укажите инфоблок в котором будут храниться картинки."; } } function GetPublicViewHTML($arProperty, $value, $strHTMLControlName) { $LINK_IBLOCK_ID = intval($arProperty["LINK_IBLOCK_ID"]); if($LINK_IBLOCK_ID) { $ELEMENT_ID = intval($value["VALUE"]); if($ELEMENT_ID) { $rsElement = CIBlockElement::GetList(array(), array("IBLOCK_ID" => $arProperty["LINK_IBLOCK_ID"], "ID" => $value["VALUE"]), false, false, array("ID", "PREVIEW_PICTURE", "DETAIL_PICTURE")); $arElement = $rsElement->Fetch(); if(is_array($arElement)) return CFile::Show2Images($arElement["PREVIEW_PICTURE"], $arElement["DETAIL_PICTURE"]); } } return ""; } function ConvertToDB($arProperty, $value) { // xmp($value);die; $arResult = array("VALUE" => "", "DESCRIPTION" => ""); $LINK_IBLOCK_ID = intval($arProperty["LINK_IBLOCK_ID"]); if($LINK_IBLOCK_ID) { if( is_array($value["VALUE"]) && is_array($value["VALUE"]["error"]) && $value["VALUE"]["error"]["VALUE"] == 0 && $value["VALUE"]["size"]["VALUE"] > 0 ) { $arDetailPicture = array( "name" => $value["VALUE"]["name"]["VALUE"], "type" => $value["VALUE"]["type"]["VALUE"], "tmp_name" => $value["VALUE"]["tmp_name"]["VALUE"], "error" => $value["VALUE"]["error"]["VALUE"], "size" => $value["VALUE"]["size"]["VALUE"], ); $obElement = new CIBlockElement; $arResult["VALUE"] = $obElement->Add(array( "IBLOCK_ID" => $LINK_IBLOCK_ID, "NAME" => $arDetailPicture["name"], "DETAIL_PICTURE" => $arDetailPicture, ), false, false, true); } elseif( is_array($value["VALUE"]) && isset($value["VALUE"]["size"]) && !is_array($value["VALUE"]["size"]) && $value["VALUE"]["size"] > 0 ) { $arDetailPicture = array( "name" => $value["VALUE"]["name"], "type" => $value["VALUE"]["type"], "tmp_name" => $value["VALUE"]["tmp_name"], "error" => intval($value["VALUE"]["error"]), "size" => $value["VALUE"]["size"], ); $obElement = new CIBlockElement; $arResult["VALUE"] = $obElement->Add(array( "IBLOCK_ID" => $LINK_IBLOCK_ID, "NAME" => $arDetailPicture["name"], "DETAIL_PICTURE" => $arDetailPicture, ), false, false, true); } elseif($value["VALUE"]["del"]) { $obElement = new CIBlockElement; $obElement->Delete($value["VALUE"]["old"]); } elseif($value["VALUE"]["old"]) { if ($value["VALUE"]["sort"] != '') { $obElement = new CIBlockElement; $obElement->Update($value["VALUE"]["old"], array('SORT' => $value["VALUE"]["sort"])); } $arResult["VALUE"] = $value["VALUE"]["old"]; } elseif(!is_array($value["VALUE"]) && intval($value["VALUE"])) { $arResult["VALUE"] = $value["VALUE"]; } } return $arResult; } function OnBeforeIBlockElementDelete($ELEMENT_ID) { $arProperties = array(); $rsElement = CIBlockElement::GetList(array(), array("ID" => $ELEMENT_ID), false, false, array("ID", "IBLOCK_ID")); $arElement = $rsElement->Fetch(); if($arElement) { $rsProperties = CIBlockProperty::GetList(array(), array("IBLOCK_ID" => $arElement["IBLOCK_ID"], "USER_TYPE" => "Picture")); while($arProperty = $rsProperties->Fetch()) $arProperties[] = $arProperty; } $arElements = array(); foreach($arProperties as $arProperty) { $rsPropValues = CIBlockElement::GetProperty($arElement["IBLOCK_ID"], $arElement["ID"], array( "EMPTY" => "N", "ID" => $arProperty["ID"], )); while($arPropValue = $rsPropValues->Fetch()) { $ID = intval($arPropValue["VALUE"]); if($ID > 0) $arElements[$ID] = $ID; } } foreach($arElements as $to_delete) { CIBlockElement::Delete($to_delete); } } }