В процессе добавления галочек "Пользовательского соглашения..." во все формы на сайте, столкнулся с некоторой особенностью формы восстановления пароля. Учитывая неопределённость законодательства, решил добавить галочку и в эту форму, поскольку пользователь отправляет в ней свой e-mail, а в данном проекте ещё и телефон. Особенность заключалась в том, что даже переместив компонент system.auth.forgotpasswd в свой неймспейс добраться до самой отправки письма с контрольной строчкой нельзя. В компоненте этого ничего нет. Соответственно и запретить отправку данных, если в форме не отмечена галочка компонент тоже никак не позволяет. Решением было сделать свой обработчик на событие OnBeforeUserSendPassword - он вызывается как раз перед отправкой письма восстановления Далее в нём достаточно проверить, передана ли галочка и вызвать исключение, если не передана с соответствующим сообщением. Примерный код обработчика:
function OnBeforeUserSendPassword(&$arFields) {
//Проверяем, установлена ли галочка на чекбоксе согласия
if ((!isset($_POST["accept_agreement"])) || ($_POST["accept_agreement"] != 1)) {
global $APPLICATION;
$APPLICATION->throwException("Подтвердите согласие с \"Пользовательским соглашением об обработке персональных данных\"");
return false;
}
}
как можно блок bitrix:main.include преобразовать в нормальный чтоб на каждой странице одного и того же текста не было? вот код если что "вставка включаемой области"
<div class="sectiontext"> <?$APPLICATION->IncludeComponent( "bitrix:main.include", "template4", array( "AREA_FILE_SHOW" => "page", // Показывать включаемую область "PATH" => "", "EDIT_TEMPLATE" => "", // Шаблон области по умолчанию "AREA_FILE_SUFFIX" => "", // Суффикс имени файла включаемой области ), false, array("ACTIVE_COMPONENT" => "N") );?> </div>
помогите пожалуйста кто знает, текст который был в этом блоке пропал на всех страницах и появился один и тот же.
Постоянно занимаюсь интеграцией 1с и сайтов битрикс. Немного устал сравнивать товары из 1С и сайта между собой. Написал удобный механизм сравнения. Возможно кому-то пригодится эта обработка в работе
Запущенная обработка стучится на определенный скрипт сайта (входит в поставку) и получает сведения о состоянии товаров на сайте. Дальше в удобной форме показывается сравнение данных- активности, цен, остатков, картинок и других полей по основному товару и характеристикам номенклатуры. Больше не нужно делать сравнение руками и тратить на это время.
Когда загружаются файлы (к задаче или комментарию задачи) производится работа с модулем диска. Сразу после загрузки файлы попадают в раздел «Загруженные файлы» на диске:
До недавнего времени при удалении задачи или комментария к ней, файл всегда оставался в модуле диска. При таком подходе при большом количестве пользователей и задач портал стремительно разрастается, что приводит к необходимости постоянно расширять доступное место.
В целом, каждый пользователь может зайти на свой диск, посмотреть каждый файл, используется ли он где, и если нет, то удалить его. Но когда файлов очень много, это практически невыполнимая задача.
На текущий момент (версия 17.0.9):
При удалении комментария к задаче файлы стали удалятся
При удалении самой задачи – не удаляются ни файлы комментариев, ни файлы самой задачи.
Почему так происходит и как это исправить описано ниже.
Структура в базе
Для начала немного о том, какие сущности создаются в базе при прикреплении файла:
Создается запись о самом файле в таблице b_file
Создается запись о файле, как об объекте диска в таблице b_disk_object. Содержит ID файла из b_file, тип, хранилище (у какого пользователя расположен, в какой директории) и прочие поля.
Создается запись в таблице b_disk_attached_object, в который хранится информация о том, к каким сущностям прикреплен объект диска. Например, если объект был прикреплен к 26 задаче, то основные поля записи будут выглядеть так:
В задаче заполняется пользовательское поле UF_TASK_WEBDAV_FILES, которое содержит ID записей из таблицы b_disk_attached_object
Аналогичная ситуация происходит с прикреплением файлов к комментарию задачи. Таблица с пользовательскими полями - b_uts_forum_message
Удаление комментария к задаче.
Комментарии к задаче основаны на модуле форума. При удалении комментария:
Внутри вызывается метод CAllForumMessage::Delete, который приводит к вызову удаления значений пользовательских полей для задачи $USER_FIELD_MANAGER->Delete("FORUM_MESSAGE", $ID);
Наше пользовательское поле с файлами имеет класс Bitrix\Disk\Uf\FileUserType. Для этого класса вызывается метод ondelete
Тот в свою очередь удаляет привязку объекта диска к комментарию (запись в b_disk_attached_object), а также если больше привязок не осталось, то удаляется и сам файл (в версии 16.0.13 удаления самого файла ещё нет)
Удаление задачи Удаление задачи по факту осуществляется методом CTasks::Delete (после вызова CTaskItem::delete). Внутри есть вызов метода удаления темы форума (комментариев к задаче)
которая по сути является оберткой для: \CForumTopic::Delete($id);
Если посмотреть код этого метода, то будет видно, что события в нем никакие не вызываются, записи удаляются напрямую из базы.
$DB->Query("DELETE FR OM b_forum_message WH ERE TOPIC_ID = ".$ID."");
В результате чего и сами привязки в b_disk_attached_object и файлы остаются на месте (как для задачи, так и для комментариев).
Запись TODO внушает надежды, но неизвестно, когда это произойдет
Решение
В версии 17 достаточно выполнить следующие действия:
Для удаления файлов в комментариях к задаче:
Регистрируем обработчик onBeforeTopicDelete, который вызывается до удаления темы форума. В нем выбираем все сообщения и сохраняем в статическую переменную
Регистрируем обработчик onAfterTopicDelete, который вызывается после удаления темы форума, для каждого сообщения вызываем: $USER_FIELD_MANAGER->Delete("FORUM_MESSAGE", $messageId);
Таким образом $USER_FIELD_MANAGER сам произведет все необходимые действия
Для удаления файлов самой задачи:
Сами задачи из системы не удаляются. Удаляются различные привязки, но для самих задач ставится флаг ZOMBIE в таблице. Если не используется CRM или какие-то собственные значащие пользовательские поля, то для задачи так же повесить обработчик OnTaskDelete и внутри вызвать $USER_FIELD_MANAGER->Delete("TASKS_TASK", $id);
До 17 версии дела обстоят немного хуже. Поскольку при отсутствии привязок к сущностям удаление файла не производится (код для этого действия в метод \Bitrix\Disk\AttachedObject::delete был добавлен примерно в версиях 16.5 – 17) Необходимо принудительно собирать список файлов, привязанных к сущности и после её удаления, удалять их.
Примерный код классов для версий 17 и ниже находится во вложении (local.rar)
Обновил своего старичка с 12.0.3 до 17.0.9 (редакция старт) Хоть и такая маленькая редакция, но если посмотреть на коммит Измененные файлы (12594) Обновление длилось минут 5. Сайт очень простой, ну совсем простой. Пара страниц и один раздел с bitrix:news Каких-то изменений по скорости я не обнаружил, он и так меньше 0.1 секунд грузится.
Теперь тестируем производительность. Хостинг Timeweb
php 5.3.29 До обновления:
Конфигурация
21.98
30
Среднее время отклика
0.0455
0.0330
секунд
Процессор (CPU)
6.9
9.0
миллионов операций в секунду
Файловая система
8 560.1
10 000
файловых операций в секунду
Почтовая система
0.0136
0.0100
время отправки одного письма (в секундах)
Время старта сессии
0.0001
0.0002
секунд
Конфигурация PHP
оптимально
оптимально
База данных MySQL (запись)
5 554
5 600
количество запросов на запись в секунду
База данных MySQL (чтение)
13 685
7 800
количество запросов на чтение в секунду
База данных MySQL (изменение)
4 748
5 800
количество запросов на изменение в секунду
После обновления:
Конфигурация
58.10
30
Среднее время отклика
0.0172
0.0330
секунд
Процессор (CPU)
9.6
9.0
миллионов операций в секунду
Файловая система
9 654.2
10 000
файловых операций в секунду
Почтовая система
0.0086
0.0100
время отправки одного письма (в секундах)
Время старта сессии
0.0001
0.0002
секунд
Конфигурация PHP
оптимально
оптимально
База данных MySQL (запись)
7 758
5 600
количество запросов на запись в секунду
База данных MySQL (чтение)
18 858
7 800
количество запросов на чтение в секунду
База данных MySQL (изменение)
8 409
5 800
количество запросов на изменение в секунду
Перешел на php 7.0
Конфигурация
120.16
30
Среднее время отклика
0.0083
0.0330
секунд
Процессор (CPU)
40.6
9.0
миллионов операций в секунду
Файловая система
11 811.2
10 000
файловых операций в секунду
Почтовая система
0.0077
0.0100
время отправки одного письма (в секундах)
Время старта сессии
0.0001
0.0002
секунд
Конфигурация PHP
оптимально
оптимально
База данных MySQL (запись)
8 963
5 600
количество запросов на запись в секунду
База данных MySQL (чтение)
28 738
7 800
количество запросов на чтение в секунду
База данных MySQL (изменение)
10 006
5 800
количество запросов на изменение в секунду
Конечно было бы здорово потестировать обновление какого-то старого магазина... Надеюсь скоро будет обновление одного старого городского портала, тогда так же отпишусь.
Мы, как и любая другая команда, постоянно сталкиваемся с проблемами обновления проектов на production-серверах. Самый простой способ заставить проект не работать - допустить ошибку при обновлении.
Есть два способа избегать неприятностей подобного рода:
Мотивировать команду быть сосредоточенными при обновлении, составить пошаговый план и не пропустить всех пунктов сценария обновления;
Максимально автоматизировать процесс обновления production-сервера проекта, тем самым снизить роль человеческого фактора.
Для себя выбрали второй вариант и не ошиблись, но путь этот был не таким безоблачным как нам бы этого хотелось.
Одной из наших специализаций является разработка проектов на платформе “1С Битрикс”. Решения по развороту и обновлению продукта не входят в коробку. Проанализировав доступные решения на тот момент, мы пришли к выводу что подходящих не существует и для необходимой автоматизации придется реализовывать решение самостоятельно.
Если проблему обновления исходного кода за нас решает система версионирования, то с базой данных дела обстоят иначе. Наиболее популярным решением обновлений баз данных являются – это такая абстракция, при которой все изменения в базе данных осуществляются специально подготовленным исходным кодом (сценариями миграций или проще говоря миграциями).
Так вышел на свет наш с поддержкой механизма автоматических миграций (миграции создаются без программистов на основе реакций на изменения состояний сущностей через обработку событий). При выпуске это было преимуществом, но потом, как выяснилось, это стало недостатком. Постоянный поток трудностей связанных с автоматическим обновлением заставил нас усомниться в правильности решения. Конечно, впоследствии появились и сценарии миграций которые создаются программистом, но автоматические также приходилось поддерживать. Проанализировав трудности применения модуля была разработана . Ниже перечислим главные преимущества решения.
Стабильность
За миграцию отвечает программист. Модуль миграций используется как инструмент, не пытаясь возложить на себя ответственность по развороту конкретных данных и схем. Процесс каждой миграции запускается исходным кодом. Модуль только определяет очередность выполнения.
Учет времени обновления
Для каждой миграции можно задать примерное время выполнения. Перед обновлением это время можно просуммировать и определить длительность сессии обновления. Это очень важно при обновлении production-сервера проекта. К примеру, если у вас есть список миграций которые обновляются два часа, то лучше запускать обновление ночью, если же время не превышает и одной секунды, то можно смело обновиться и днем.
Приоритет выполнения
Такая потребность возникла в тот момент, когда миграции повсеместно стали использоваться и как инструмент актуализации данных. Например, обратиться к внешнему источнику и обновить контент у себя на проекте. Такие сценарии нужны для одноразового использования на проекте и миграции как нельзя лучше подходят на эту роль. Они гарантируют что исходный код одной миграции будет выполнен только один раз. Правда такие миграции как раз и мешают при большом обновлении, потому что их время выполнения обычно большое, а в очереди стоят миграции которые работают со схемой данных без выполнения которых проект просто не будет работает. Тут и возникло решение внедрить понятие приоритета выполнения. Таким образом миграциям, которые меняет схему данных проекта, программист должен установить наивысший приоритет, что обеспечит их немедленное выполнение, а “долгие” миграции будут выполняться уже после. Такое решение обеспечило необходимую стабильность обновлению.
Удобная работа через консоль
При выпуске первого модуля мы не уделили терминалу должного внимания и все управление миграциями реализовали через web интерфейс. Это была еще одна наша ошибка, так как web интерфейс не обеспечивает нам необходимой стабильности. При обновлении разработчик в основном взаимодействует с системой через ssh-интерфейс: он обновляет исходный код, обновляет сторонние библиотеки и web-интерфейс миграций данных нарушал эту единую точку входа. Теперь основная работа с миграциями организована через консоль, со множеством удобной информации,что обеспечивает единый интерфейс и повышает устойчивость обновления проекта.
Решение доступно каждому желающему , в планах есть дальнейшая поддержка решения. Мы заботимся о том чтобы сделать наш труд более профессиональным.
Доброго дня каждому. Сегодня я приведу маленький хак, на который случайно наткнулся буквально только-что Допустим имеется инфоблок "Аксессуары", тип "Каталоги" (catalog)
Нам нужно его переместить в тип "Справочники" (references) Делаем так: 1) открываем инфоблок на редактирование ссылка в адресной строке получится типа такой /bitrix/admin/iblock_edit.php?type=catalog&lang=ru&ID=26&admin=Y
2) заменяем код catalog на код нужного нам типа инфоблоков (в данном случае references). Жмём enter. Страница открылась по новой.
3) Жмём "Применить" или "Сохранить" 4) И о, чудо - инфоблок переехал в другой тип
Уважаемые коллеги! Приглашаю на бесплатный вебинар 27 июня, где я покажу, что нужно сделать для подключения онлайн-касс, а что делать не стоит. Какие есть подводные камни обновлений до 17-й версии. Порекомендуйте вебинар клиентам, приходите сами.
Онлайн-кассами, фискальными регистраторами, выбором ОФД интернет-магазины пугают с 2016 года. «Кто сегодня не успеет, завтра крепко пожалеет», — говорит герой одной черной комедии. Но совсем скоро 1 июля, онлайн-кассы станут обязательными, и бизнесу совсем не до шуток. На вебинаре 27 июня 2017 года «Инфоспайс» покажет, что нужно сделать для подключения онлайн-касс в интернет-магазинах на платформе «1С-Битрикс» и какие сложности могут возникнуть. Отступать некуда — впереди 54-ФЗ!
Информации на рынке намного больше, чем работающих онлайн-касс. Пока утрясаются технические и законодательные неопределенности, мы предлагаем зарядиться знаниями, как подготовить интернет-магазин на платформе «1С-Битрикс» к переходу на онлайн-кассы и как организовать новые бизнес-процессы интернет-магазина в связи изменениями в 54-ФЗ.
Во вторник 27 июня с 11.00 до 12.15 часов по московскому времени мы расскажем о подготовительной работе, без которой интернет-магазинам будет невозможно запустить онлайн-кассы.
На вебинаре мы не рекламируем сервисы или услуги подключения онлайн-касс. Мы стараемся наглядно показать, какие сложности могут возникнуть при подготовке интернет-магазина к подключению онлайн-касс. Предупрежден — значит защищен!
В программе:
Алгоритм подключения онлайн-касс.
Ответ на главный для многих вопрос: а можно ли не обновлять платформу «1С-Битрикс»?
Типизация проблем при обновлении до 17-й версии «1С-Битрикс: Управление сайтом» и способы их устранения.
Что делать, если Вы уже опаздали с подключением.
Мониторинг доступности онлайн-касс и сервис Sensorium.cloud.
Дата премьеры:
27 июня 2017 года, с 11.00 до 12.15.
Хронометраж:
60 минут на доклад.
15 минут на вопросы участников вебинара.
Среди приглашенных:
Интернет-магазины, которые все еще без онлайн-касс.
Те, кто только собираются обновлять «1С-Битрикс: Управление сайтом» до 17 версии, но почему-то откладывают.
Партнеры компании «1С-Битрикс» и 1С.
Журналисты и блогеры, пишущие про e-commerce.
Все сочувствующие отрасли e-commerce.
Условия участия:
Участие бесплатное, но места на площадке вебинара ограничены. Поэтому зарегистрируйтесь прямо сейчас и поделитесь с друзьями анонсом в соцсетях, пожалуйста.
В связи с ростом и открытием новых направлений в штат в Челябинск ищем талантливых программистов и в поиске талантливого "фронт-мена" или "фронт-вумен" (но не тех, что в квн) а тех, работой которых гордится front-end
Полный спектр вакансий представлен на сайте
При необходимости готовы рассмотреть вопрос перехода на постоянную работу в офис и команд.
В апреле мы уже запустили в бету обновления по автоподдержке отправки форм с подтверждением согласия с политикой конфиденциальности на решении
недавно оно было переведено в стабильные релизы
Детали работы описали на блогах МАркетплейс
Несколько минут демонстрацию того, как просто включить авторежим
Постскриптум Так как ограничений на типы и колчичество форм в решение нет, то возможны как ручной тюнинг форм (без программирования, конечно) этого механизма, так и включение глобалного контроля над всеми формами решения, просто решите, что для вас проще.
Коллеги, мы собираем сейчас пожелания по поводу функционала поддержки работы с прайс-листами в публичной части
Вкратце, о чем речь (что уже есть)
Данный функционал востребован многими компаниями, и обращения по нему мы получали давно. Но прорабатывался этот вопрос очень щепетильно, поэтому мы не просто подготовили поддержку публикаци прайсов, а аналогично создали возможность переплетать и встраивать ветки прайсов на уровне контента.
Что уже есть:
1. В нашем решении можно создавать любые инфоблоки для прайс-листов. 2. Можно как опубликовать целые прайсы,так или ветки этих прайсов на нужных вам страницах 3. Можно автоматически включить поддержку прайсов на любой странице элемента (при этом есть возможность создавать связи как на уровне разделов, так и на уровне элементов с нужными ветками прайсов)
Два коротких видео-ролика о возможностях
SmartPrice Часть 1
SmartPrice Часть 2
А теперь главное (Зачем этот пост):
У нас уже есть целый ряд задач по развитию и совершенствованию функционала
Но мы собираем предложения и советы от разработчиков, чтобы сопоставить со своими планами
Буду благодарен на ваши предложения (но предложения прошу высылать в личку)
Для ориентира несколько примеров задач: Сейчас в приоритете и в плане уже стоит: Возможность печати веток прайсов. А вот обработка и загрузка прайсов (импорт прайсов) пока думаем не делать, так как решений по ним уже достаточно, и готовы рассмотреть предложения авторов Маркетплейс, которые уже выпустили такие модули. Возможно, будем предлагать нашим клиентам.
Т.е. Для нас сейчас важен момент использования прайсов именно в публичной части + маркетинговые фишки, связанные с публикацией прайсов
Заранее благодарен за ваши предложения Особое внимание - потребностям ваших реальных клиентов, если вы обладаете этим бесценным опытом, с удовольствие бы с вами пообщался.
Частенько стала возникать потребность вставить в плавающую шапку сайта поиск по заголовкам. И столкнулись с такой проблемой, что при скролле страницы, результат быстрого поиска прилипает к верхнему левому краю экрана. Решили это следующим образом: Файл template.php компонента search.title модифицировали следующим образом:
Т.е. обращаем внимание на закоменченную часть кода в script. Ее мы убираем, а сам вызванный объект JCTitleSearch приравниваем какой то произвольной переменной. Соответственно от нее мы дальше можем наследоваться, как это сделано в коде выше по событию onkeyup для поля. Обращаем внимание на используемый метод search.onChange - это единственный метод с callback функцией, с помощью которого мы в принципе и будем манипулировать результатом поисковой выдачи используя свою функцию.
Функцию я написал следующую (но каждый может ее поправить под свои потребности):
BX.namespace('BX.MIT.SearchTitle');
(function() {
BX.MIT.SearchTitle = {
change: function(id) {
if(BX('mitBody').querySelector('div.'+id+'-result)) {
var pos = BX.pos(BX(id));
var el = BX('mitBody').querySelector('div.'+id+'-result');
var top = 70;
if(pos.top < 70) {
top = pos.top + pos.height;
}
BX.adjust(el, {
style : {
'margin-left': pos.left + "px",
left: "0px",
top: top + "px",
position:"fixed"
}
});
}
}
}
})();
Не обращаем особого внимания на строчку if(pos.top < 70) - это фикс для проекта над которым я работаю в данным момент. Особое внимание лучше уделить BX('mitBody') - это по сути тег body с id="mitBody" (придумаете свое если принципиально). Соответственно, что мы делаем? Полученный идентификатор поля позволяет нам с помощью метода BX.pos() узнать его реальное положение относительно видимой части сайта. Ну а дальше простым изменением элемента, который нам выводит быстрые результаты поиска мы его позиционируем ниже и левее самого поля ввода.
Собственно это все, надеюсь кому то помог с данной проблемой. А ну и конечно: Было: Стало:
Написал такую маленькую, но очень полезную штуку для отлова всех тормозных страниц на сайте. На сервере должен быть установлен и настроен Xhprof. Как это сделать - погуглите Ну или . Скрипты интерфейса Xhprof у меня лежат в директории /xhprof-0.9.4/ в корне сайта. Можете вынести в свою директорию или вообще в отдельный домен можно это все разместить, чтобы все секьюрно и правильно было. Вот, собственно, код который размещаем в /bitrix/php_interface/dbconn.php:
Данный код отлавливает все хиты, работающие больше 1 сек, и заносит их в лог xhprof. Да, есть глобальные переменные. Да, кривовато. Можете предложить своё идеальное решение в комментариях.
В результате в логах Xhprof'а увидим вот такие записи:
Дааа, работы капец как много)) В имени каждого файла отмечается тип запроса к скрипту (http или shell), путь до скрипта и время работы скрипта. Затем, попивая чай/кофе, можно спокойно проанализировать какие участки кода вам нужно доработать по вот таким наглядным графам вызова функций:
Всё. Всем удачной охоты Если кто знает, как в одном хите замерять сразу несколько участков кода и строить по ним отдельные графы, отпишитесь в комментариях, пожалуйста. Еще вот такая неприятность возникает иногда: Если знаете какие настройки xhprof или php ковырять, подскажите.
Уже довольно давно битрикс позволяет наследоваться от компонентов. Звучит круто, но после перехода на новый catalog.section звучит уже не так круто. Проблема простая - они убрали из catalog.section возможность показа нескольких цен. Убрали как? Правильно, зашили в ядре. Теперь есть только 1 цена - минимальная. Ну, думаю, не беда. Добавлю получение цен в result_modifier.php. Посмотрел количество кода и зависимостей и подумал, не-е... лучше отнаследуюсь. А то потом поддерживать. Начал наследоваться. Всё шло хорошо... первую минуту. Я хотел получить лишь список цен из свойства prices. Сперва оно заполняется относительно нужными данными по всем ценам. После чего в другом месте перезаписывается на минимальную из всех цен. После этого передаётся в элемент и в дальнейшем очищается. Хорошо, есть методы для получения raw-цен. Получил, вызвав его в своём компоненте. Но вот опять беда... Далее происходят махинации в Base::calculatePriceBlock. А происходит там следующее - по всем ценам считаются скидки, флаги и т.п., т.е. для стандартной работы всё это важно. После чего возвращает, ВНИМАНИЕ, минимальную из всех цен.
Выход лишь 1. Переопределить весь этот метод и куда-нибудь ещё сохранять цены, а потом уже из них в шаблоне выводить то, что мне нужно. К чему это приведёт? А всего-лишь к переопределению 300 строчек кода, отвечающих за цены. А как мы знаем, цены - одна из самых меняемых частей в битриксе. Ведь это основа продаж, а фичи выходят каждый мажорный релиз.
Вот прихожу к выводу, что наследование - это здорово, но вот только теперь мне придётся с каждым обновлением следить за этими 300 строчками. И это только 1 компонент. А если их 5, 10?
Пока битрикс освоил возможность наследования, но довести до ума всё ещё сложно им. Хуже только класс с 1 методом, который и можно переопределить. А всё остальное внутри метода.
P.S. Почему вы решили за нас, что список цен нам не нужен в списке элементов? Тем более, что они и так все присутствуют в расчётах. Это просто хамство. P.P.S. Ну делите как-то более качественно на методы. Ведь можно было сделать 1 метод для расчёта цен, а второй для получения минимальной цены. Это 2 разных действия. Не правда ли? P.P.P.S. Если кто знает решение этой проблемы, буду благодарен
Сравнительно недавно (не более года), на всех сайтах с БУС, которые я мониторю, наблюдаются попытки подбора пароля к админке. В Журнале событий с интервалом в 1-2 минуты появляются события "Ошибки входа" [USER_LOGIN] по URL-у /bitrix/admin/index.php?login=yes Происходит перебор пользователей с логинами admin, support, content, bitrix, <ваш домен> и т.п. Заходы происходят с конечного количества IP адресов.
Рекомендую обратить на это внимание. Полагаю, что подобное проявляется не только у меня одного.
Что делать.
а) если для вас это — новость, проверьте свои сайты (Настройки > Инструменты > Журнал событий, фильтр по [USER_LOGIN] )
б) не используйте аккаунты со "стандартными" именами: admin, support, content, bitrix, tester, manager, <ваш домен>. Если у вас есть подобные аккаунты, срочно переименуйте их во что-то менее предсказуемое.
в) заблокируйте доступ к админке (или всему сайту) по IP (список ниже). Сделать это можно через Проактивную защиту > Стоп-лист или отредактировав .htaccess (, )
г) если это возможно, используйте "Ограничение доступа к административной части".
Список IP, с которых работает бот, подбирающий пароли:
Вкратце Примерно до 2011 года я говорил клиентам так Ваш сайт сделан с соблюдением стандартов - обновляйтесь, если хотите Это была золотая эпоха Битрикс
сейчас Кто обновляет - тот берет ответственность на себя
Мы стали делать сайты хуже?
Нет просто за мой период я поймал столько сюрпризов, что организм стал требовать переждать "первой" крови
Кроме того: уже неоднократно битрикс менял и ядро и вообще АПИ настолкьо,ч то некоторые узлы просто нуждались в переделке и адаптации под новый битркис.
Но увы. Когда плотно взялись за решения МП - снова здравствуйте сюрпризы и нежданчики.
Логично, что страница сайта общим размером 2 МБ загрузится гораздо быстрее, чем та же страница, но размером 6 МБ.
Так почему бы не уменьшить размер всех страниц вашего сайта более чем в 3 раза без каких-либо побочных эффектов и буквально в 2 клика?
Сделать это можно с помощью сервиса
Ускорение достигается за счет сжатия изображений на сайте. Благодаря этой процедуре можно добиться сжатия изображений до 98%. А средний показатель сжатия - чуть выше 71%.
В результате вы получите: 1. Ускорение загрузки страниц. 2. Увеличение показателей Google Pagespeed Insights. 3. Улучшенное ранжирование сайта в поисковой выдаче. 4. Увеличение конверсии. 5. Снижение нагрузки на хостинг/сервер. 6. Экономию места на диске.
Подключение ОптиПик к сайту занимает всего несколько минут - нужно лишь зарегистрировать аккаунт и установить модуль на сайт.
Для сайтов на 1С-Битрикс у сервиса есть . Для остальных платформ и .
Сжатие картинок на сайте проходит в фоновом режиме по принципу “поставил и забыл”. Сервис сам сожмет все имеющиеся картинки на сайте. И в дальнейшем при добавлении новых картинок на сайт или изменении старых эти картинки автоматом ставятся в очередь на сжатие.
Убедиться в эффективности сжатия можно совершенно бесплатно и без регистрации - .
Есть каталог с более 60к+ товаров на сайте и надо было сделать выгрузку в YML. Как понимаете, стандартным экспортом сделать это неудалось, т.к. сервер загибался от такого кол-ва запросов и было неудобно, что XML генерился скопом.
Использовал за основу скрипт "Пошагового скрипта от Антона Долганина" ( ) за такой скрипт ему отдельное спасибо.
Файл yml_generator.php залить думаю лучше всего в /bitrix/admin/
Случилась необходимость написать свою функцию для шаблонизатора SEO-свойств инфоблока. И по задаче нужно было, чтобы функция могла работать не только с приходящими значениями свойств и полей, но и с другими данными элемента.
Нужно сделать нечто вроде этого:
namespace Custom\Iproperty\Template;
// Создает функцию-обработчик для SEO-шаблонов инфоблока
// {=namedValue "PROPERTY_CODE"} - выведет название свойства с кодом PROPERTY_CODE, двоеточие и значение свойства. Например, Ширина: 120см
class NamedValue extends \Bitrix\Iblock\Template\Functions\FunctionBase
{
// Метод добавляет нашу функцию в реестр доступных
public static function eventHandler($event)
{
$parameters = $event->getParameters();
// Обратите внимание, что название функции приходит в нижнем регистре
$functionName = $parameters[0];
if ($functionName === "namedvalue")
{
//обработчик должен вернуть SUCCESS и имя класса
//который будет отвечать за вычисления
return new \Bitrix\Main\EventResult(
\Bitrix\Main\EventResult::SUCCESS,
"Custom\IpropertyFunction\NamedValue"
);
}
}
// Метод позволяет обработать параметры - а заодно перехватить данные Entity, в данном случае это может быть инфоблок, раздел или элемент
public function onPrepareParameters(\Bitrix\Iblock\Template\Entity\Base $entity, array $parameters)
{
$arguments = array();
// Перехватываем id элемента, чтобы можно было обращаться к его свойствам
$this->data['id'] = $entity->getId();
/** @var \Bitrix\Iblock\Template\NodeBase $parameter */
foreach ($parameters as $parameter)
{
$arguments[] = $parameter->process($entity);
}
return $arguments;
}
//собственно функция выполняющая "магию"
public function calculate($parameters)
{
// Получаем все свойства инфоблока
$el = \CIBlockElement::getByID($this->data['id']);
$props = $el->getNextElement()->getProperties();
// Получаем параметры для нашей функции
$result = $this->parametersToArray($parameters);
$code = $result[0];
$property = $props[$code];
if( array_key_exists($code, $props) )
return "{$property['NAME']}: {$property['VALUE']}";
else
return '';
}
}
Если в методе onPrepareParameters посмотреть значение переменной $entity, то можно увидеть нечто вроде такого:
Мягко говоря, информации немного, но нужная нам, ID элемента, присутствует, и по ней мы уже можем вытянуть все необходимое.
Пока я копался в ядре, я сделал для себя несколько выводов: 1. Функция вызывается для разных типов $entity, по классу объекта можно получить представление, с чем мы в текущий момент работаем - элемент, раздел, инфоблок. 2. Можно без проблем вытянуть ID объекта через $entity->getId(). В случае Entity\Element это ID элемента, для Entity\Section это ID раздела, ну а для Entity\Iblock, как вы уже догадались - это ID инфоблока. 3. Жаль, что приходится много копаться в ядре, чтобы потом еще столько же делать эксперименты, чтобы получить хоть какой-то результат. Катастрофически не хватает примеров.
Разбирая шаблон catalog.bigdata.products увидел интересное решение, как обработать полученный от сервера ответ. Предположим в result содержится ответ сервера. Если сделать
$('#node').html(result);
То в результате скрипты будут вставлены как текст, выполнены они не будут. Если необходимо разобрать ответ сервера, вставить html и выполнить скрипты, полученные по ajax - поступаем следующим образом:
var ob = BX.processHTML(result);
BX(injectId).innerHTML = ob.HTML;
BX.ajax.processScripts(ob.SCRIPT);
event: 'onSelectElement' - это кастомное событие, на которое мы будем вешаться, дабы отследить, что в окошке выбрали товар. Писать там можно что угодно, хоть hrenMorjovii.
lang: 'ru' - язык сайта.
allow_select_parent: 'Y' - не экспериментировал особо с этим параметром, за что отвечает - хз. Без него тоже работает.
compileUrl - комплит урл, по которому надо получать контент окна. По сути, впихивает в урл все props, которые у нас есть.
/bitrix/admin/esd_element_search_dialog.php - кастомная страница вызова компонента, которую мы создали, и положили вызов компонента, аналогично /bitrix/modules/catalog/admin/cat_product_search_dialog.php
dialogSearch - формирует объект админского диалогового окна. Подробности тут и как всегда в исходниках /bitrix/js/main/core/core_window.js.
У этого объекта есть параметр content_url, если его указать, то контент в окно будет аяксом подтянут по этому урлу. Это нам и нужно.
И в файле, где нам это окно нужно использовать:
import ElementSearch from './ElementSearch';
const dialog = new ElementSearch({ IBLOCK_ID: 147 });
dialog.dialogSearch().getDialog().Show();
Параметр IBLOCK_ID - отвечает за тот инфоблок, с которого надо тянуть элементы.
Метод dialog.dialogSearch().getDialog().Show(); отвечает за показ окна. Я его здесь вызвал при отработке скрипта, но его можно обернуть в какой-нибудь onClick и вызывать в нем. Это уже люди сами разберутся, где и как юзать.
Для отслеживания выбора элементов повесимся на событие, которое мы указали в объекте.
BX.addCustomEvent(dialog.getEvent(), (dataEvent) => {
console.info(dataEvent); // данные о выбранном элементе.
dialog.getDialog().Close(); // закроем окно
});
По дефолту это окно выбирает только те инфоблоки, которые отмечены как торговые каталоги.
Если же нам надо выбрать вообще любой ИБ, то нужно кастомизировать компонент. Благо он сделан с использованием class.php.
Копируем компонент bitrix:catalog.product.search в свое пространство.
Пересоздаем class.php, вызываем в нем подключение родительского класса.
<?php
/** @var \CBitrixComponent $this */
/** @var array $arParams */
/** @var array $arResult */
/** @var string $componentPath */
/** @var string $componentName */
/** @var string $componentTemplate */
/** @var \CBitrixComponent $component */
/** @global \CUser $USER */
/** @global \CMain $APPLICATION */
use Bitrix\Main\Loader;
use Bitrix\Iblock;
Loader::includeModule('iblock');
CBitrixComponent::includeComponentClass('bitrix:catalog.product.search');
class AdminElementSearchComponent extends ProductSearchComponent
{
protected function checkIblockAccess()
{
return true; // это чтоб не проверять, что у нас только каталоги и разрешать все ИБ
}
protected function getIblockList()
{
if ($this->iblockList === null){
$oResult = Iblock\IblockTable::getList([
'filter' => ['=ACTIVE' => 'Y'],
'sel ect' => ['*'],
]);
while ($row = $oResult->fetch()) {
$this->iblockList[$row['ID']] = $row;
}
}
return $this->iblockList;
}
protected function getIblockId()
{
return $this->arParams['IBLOCK_ID'];
}
}
Переопределяем несколько методов.
checkIblockAccess() - чтоб не проверять, что у нас только каталоги и разрешать все ИБ.
getIblockList() - скажет компоненту, какие ИБ можно выбирать в окошке. Собственно, тут же можно сформировать свой список, если задача того требует.
getIblockId() - чтобы тоже избежать проверок на принадлежность ИБ к каталогу, и показывать ИБ из $_GET в изначальной отрисовке окна. Грубо говоря, чтоб в arParams['IBLOCK_ID'] попал ИБ, который мы в js засунули.
Далее, в админке, на своей странице меняем вызов компонента на свой. И в конструктор объекта можно передавать новый урл.
const dialog = new ElementSearch({
IBLOCK_ID: 147,
url: '/bitrix/admin/new_search_element.php'
});
Листинг вызова окошка.
import ElementSearch fr om './ElementSearch';
BX(function(){
const dialog = new ElementSearch({
IBLOCK_ID: 147,
url: '/bitrix/admin/new_search_element.php'
});
dialog.dialogSearch().getDialog().Show();
})
Здравствуйте! Есть проблема дублей страниц. Установлена последняя версия 1C Bitrix 17. Для элементов разделов в Bitrix прописывается атрибут rel="canonical". Однако, осталась проблема дублей страниц разделов.
Как для этих страниц прописать каноническую ссылку? может быть есть решение, чтобы не генерировались дублирующие страницы разделов.