Михаил Базаров: Сообщения

Михаил Базаров

Дата последнего входа: вчера в 17:53
Дата регистрации: 7 Февраля 2012 21:17
День рождения: 7 ноября
Пол: Мужской
Михаил Базаров -> Всем
10 мая 12:53
Вывести количество не прочитанных, персональных сообщений форума в любом месте сайта.

Что бы вывести количество не прочитанных (именно персональных) сообщений из модуля форума.
В любом, нужном, месте сайта вызываем метод
<?
CModule::IncludeModule("forum");
      $messs = CForumPrivateMessage::GetNewPM(
              array("FOLDER_ID" => 1)
     );
?>

<?
 echo $messs['UNREAD_PM']
?>

Михаил Базаров -> Всем
25 февраля 15:48
Компонент добавления элемента в инфоблок с отправкой письма о добавлении и AJAX отправкой.

Сделан по быстрому, в качестве базовой заготовки для дальнейшего развития.
Развиваться будет, в полноценный компонент, в рамках видеокурса "Разработка доски объявлений на Битрикс" https://bxstore.ru/

Пока, можно использовать как форму обратной связи, с записью в инфоблок и отправкой письма.

На данный момент умеет:
- Выводить, на заполнение,  свойства инфоблока. Только не множественные.
- Загружать файлы в свойство "Файл". Использует штатный компонент main.file.input (dragn_n_drop).
- Защита, от совсем простых ботов (проверка скрытого поля на заполнение)
- Поддерживает AJAX
- Отправляет письмо о добавлении элемента
- Все параметры управляемые (картинка 1)
- Шаблон маскимально простой (картинка 2)
- Легко дорабатывается, управляется и расширяется.

Письма отправляет обычной функцией php-mail, но в файле component.php есть закомментированый участок
(картинка 3):
Можно использовать штатный метод Битрикс Event::send - который передаст поля в штатное же почтовое событие FEEDBACK_FORM

Пример работы: https://camouf.ru/1/index.php

PS: В рамках видеокурса будет превращен в полноценный компонент добавления объявления на доску. С гугло капчей, работой с любыми типами полей И так далее.

Фото:
feedback.form.element.zip ( 25.08 КБ)
Михаил Базаров
Создаем массив со свойствами файлов, методом CFile::MakeFileArray и передаем в $PROP["MORE_PHOTO"] (в моем случае, свойство с доп картинками)
$arMorePhoto["VALUE"];
$i = 0;    
foreach ($_POST["MORE_PHOTO"] as $morePhoto) {        
      $arMorePhoto['n'.$i] = array("VALUE"=>CFile::MakeFileArray($morePhoto));        
      $i++;
}
$PROP["MORE_PHOTO"] = $arMorePhoto;

Михаил Базаров -> Всем
1 апреля 11:05
Заполнить коэффициент единицы измерения (MEASURE_RATIO) из свойства элемента.

Перенесено в блог: https://camouf.ru/blog-note/9255/
Михаил Базаров -> Всем
20 марта 2019 10:57
bitrix.sale.order.ajax раскрыть блоки доставки и оплаты.

Если в компоненте одношагового оформления заказа, нужно раскрыть блоки доставки и оплаты:
В самый низ template.php добавляем
$(window).on('ready', function(event){
    BX.Sale.OrderAjaxComponent.editDeliveryBlock(true);
    BX.Sale.OrderAjaxComponent.editPaySystemBlock(true);
});
Для блоков оплаты и доставки добавляем селектор bx-selected

Тоже самое, можно делать со всеми блоками:
BX.Sale.OrderAjaxComponent.editActiveBasketBlock(true);
BX.Sale.OrderAjaxComponent.editActiveRegionBlock(true);
BX.Sale.OrderAjaxComponent.this.editActiveDeliveryBlock(true);
BX.Sale.OrderAjaxComponent.editActivePaySystemBlock(true);
BX.Sale.OrderAjaxComponent.editActivePickUpBlock(true);
BX.Sale.OrderAjaxComponent.editActivePropsBlock(true);

И можно убрать кнопки "Далее - Назад" в файле order_ajax.js

Для доставки: найти и закомментировать
this.getBlockFooter(deliveryContent);
Для оплаты:
this.getBlockFooter(paySystemContent);

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

   BX.Sale.OrderAjaxComponent.editActiveDeliveryBlock(true);
   BX.Sale.OrderAjaxComponent.editActivePaySystemBlock(true);
...

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

1. комментируем строчки:
/*if (this.activeSectionId !== this.regionBlockNode.id)
this.editFadeRegionContent(this.regionBlockNode.querySelector('.bx-soa-section-content'));

if (this.activeSectionId != this.propsBlockNode.id)
this.editFadePropsContent(this.propsBlockNode.querySelector('.bx-soa-section-content'));*/

2. меняем:
var active = section.id == this.activeSectionId,

на:
var active = true,

3. скрываем кнопки "далее" и "назад" и изменить стилями:
.pull-left.btn-default.btn-md, .pull-right.btn-default.btn-md, .bx-soa-editstep {
   display: none!important;
}
Михаил Базаров -> Всем
10 марта 13:26
Вывести дату создания файла в формате сайта

Что бы это сделать можно воспользоваться методом
CFile::GetFileArray

В параметр передаем ID нужного файла или переменную с нужным ID и классом DateTime
приводим к строке:
<?
$arItem = 123; // ID нужного файла
$rsFile = CFile::GetFileArray($arItem);
echo $rsFile['TIMESTAMP_X']->toString();
?>
Если нужна вся информация о конкретном файле (вес, формат, путь на сервере, описание итд)
Распечатываем массив
<?
print_r($rsFile);
?>

Михаил Базаров -> Всем
18 июня 2018 3:57
Вывести разделы инфоблока по первым буквам (алфавитный указатель типа) не меняя структуру каталога.

Например: у нас есть инфоблок с большим количеством разделов (картинка 1).
И мы хотим, на выводе на сайте разбить разделы по буквам (картинка 2).

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

Можно поступить следующим образом:
В шаблоне компонента catalog.section.list (Разделы инфоблока) удаляем все и меняем на такой код:
<?
foreach ($arResult["SECTIONS"] as $arSectionArray) {
      $sectFName = $arSectionArray['NAME'];
      $sectFLetter = mb_substr($sectFName, 0, 1, 'UTF-8');
      $arrayFirsletter .= '\'' . $sectFLetter . '\',';
}

eval('$FirstLetter=array(' . $arrayFirsletter . ');');
extract($FirstLetter);
$uniuLetter = array_unique($FirstLetter);

foreach ($uniuLetter as $onlyOnceLetter) {
       echo '<h3>' . $onlyOnceLetter . '</h3>';
      foreach ($arResult["SECTIONS"] as $arSection) {
         if (mb_substr($arSection['NAME'], 0, 1) == $onlyOnceLetter) { ?>
             <a href="<?= $arSection["SECTION_PAGE_URL"] ?>">
                 <?echo $arSection['NAME']; ?>
            </a>
          <?
          }
     }
}
?>

Пояснения:

Сначала собираем первые буквы всех разделов в одну переменную $arrayFirsletter , так как названия разделов
могут быть как на латинице, так и на кириллице используем mb_substr- с помощью которого и "отрубили" первые буквы названий разделов
foreach ($arResult["SECTIONS"] as $arSectionArray) {
      $sectFName = $arSectionArray['NAME'];
      $sectFLetter = mb_substr($sectFName, 0, 1, 'UTF-8');
      $arrayFirsletter .= '\'' . $sectFLetter . '\',';
}

Далее, с помощью eval, загоняем все буквы в массив array. Так как первые буквы разделов могут повторяться. Переводим array в array_unique - он отберет только уникальные буквы (то бишь без повторов)
eval('$FirstLetter=array(' . $arrayFirsletter . ');');
extract($FirstLetter);
$uniuLetter = array_unique($FirstLetter);

Собственно выводим эти буквы с помощью foreach
foreach ($uniuLetter as $onlyOnceLetter) {
       echo '<h3>' . $onlyOnceLetter . '</h3>';

Внутри которого еще один foreach - который отберет все разделы, начинающиеся на конкретную букву, ну и ссылка на раздел в каталоге.
Если первая буква названия раздела, совпадает с переменной $onlyOnceLetter (в которой, собственно первая буква)
foreach ($arResult["SECTIONS"] as $arSection) {
         if (mb_substr($arSection['NAME'], 0, 1) == $onlyOnceLetter) { ?>
             <a href="<?= $arSection["SECTION_PAGE_URL"] ?>">
                 <?echo $arSection['NAME']; ?>
            </a>
         



Фото:
Михаил Базаров
Кого коробит использование eval. В принципе не рекомендую им злоупотреблять.
Можно сразу загнать результат работы foreach в массив

$FirstLetter   = array();
foreach ($arResult["SECTIONS"] as $arSectionArray) {
     $sectFName = $arSectionArray['NAME'];
     $sectFLetter = mb_substr($sectFName, 0, 1, 'UTF-8');
     $FirstLetter[]   = $sectFLetter;
}
Андрей Белый
Спасибо, Михаил
Все работает!)
Михаил Базаров -> Всем
13 января 7:52
Ошибка "Mysql query error: (1146) Table '.b_sale_trading_platform' doesn't exist (400)" при просмотре заказа в Битрикс

Если, при попытке просмотреть подробную информацию о заказе, получаете ошибку
"Mysql query error: (1146) Table '.b_sale_trading_platform' doesn't exist (400)"

Ошибка может возникнуть при обновлении ядра Битрикс, если прыгаете с версии 17 на 20 и выше.

Удалите, лишний файл /bitrix/modules/sale/lib/tradingplatform.php
Его не должно быть в ядре, после этого проблема решится.

Возможно файл появился после восстановления сайта из резервной копии или перезагрузки файлов ядра.
Ранее этот файл по ошибке был добавлен, но с версии sale 17.8.25 (18.0.3) его убрали.

PS: Если, при просмотре заказа, видите только:
"Произошла ошибка, включите расширенный вывод ошибок в .settings.php"
Откройте файл /bitrix/.settings.php и переключите "debug" = "false" в "debug" = "true"



Михаил Базаров -> Всем
19 декабря 2019 6:10
Скрипт для иммитации боковой панели, выезжающей\исчезающей при протягивании пальцем по экрану.
Пригодится для мобильных версий сайтов или мобильных приложений на cordova

Подробнее тут https://github.com/mango/slideout/releases/
slideout-1.0.1.zip ( 30.02 КБ)
Mango/slideout
A touch slideout navigation menu for your mobile web apps. - Mango/slideout
Михаил Базаров -> Всем
17 декабря 2019 15:23
Pull to refresh, не большой скрипт  для обновления страницы, при перетягивании, на мобильных телефонах.
Можно использовать и в мобильном приложении на cordova/phonegap

API методы тут
https://github.com/BoxFactura/pulltorefresh.js
pull_ref.min.js ( 9.45 КБ)
BoxFactura/pulltorefresh.js
A quick and powerful plugin for your pull-to-refresh needs in your webapp. - BoxFactura/pulltorefresh.js
Михаил Базаров -> Всем
28 ноября 2019 11:17
Установить/скопировать значение свойства элемента из другого свойства, при создании или редактирования элемента инфоблока.

У нас есть свойство инфоблока с кодом ATT_PRICE
И есть свойство с кодом ATT_TEST

Задача: при редактировании элемента копировать значение из ATT_PRICE в ATT_TEST

Добавляем в init.php
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "OnAfterIBlockEl");
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "OnAfterIBlockEl");
function OnAfterIBlockEl(&$arFields) {
  if (CModule::IncludeModule("iblock")):
     $getProperty = CIBlockElement::GetList (
         Array("ID" => "ASC"),
         Array("IBLOCK_ID" => $arFields['IBLOCK_ID'], "ID" => $arFields['ID']),
        false,
        false,
        Array(
           'PROPERTY_ATT_PRICE'
         )
    );
    while($ar_fields = $getProperty->GetNext())
    {
         $setProperty= $ar_fields['PROPERTY_ATT_PRICE_VALUE'];
    }
   endif;
CIBlockElement::SetPropertyValuesEx (
      $arFields['ID'],$arFields['IBLOCK_ID'],array (
             'ATT_TEST' => $setProperty
          )
     );
}
Здесь: с помощью  CIBlockElement::GetList получили значение свойства ATT_PRICE для элемента с ID = $arFields['ID'] (текущий редактируемый/добавляемый элемент)
С помощью CIBlockElement::SetPropertyValuesEx установили значение ATT_PRICE в ATT_TEST
Михаил Базаров
Не большое улучшение. Так как работаем с одним, конкретным элементом- за раз. Можно заменить
CIBlockElement::GetList на CIBlockElement::GetByID - будет работать бодрее и так правильнее
<?
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "OnAfterIBlockEl");
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "OnAfterIBlockEl");
function OnAfterIBlockEl(&$arFields) {
if (CModule::IncludeModule("iblock")):
 $res = CIBlockElement::GetByID($arFields['ID']);
 if($obRes = $res->GetNextElement())
 {
     $ar_res = $obRes->GetProperty("ATT_PRICE");
     $setProperty = $ar_res['VALUE'];
 }
endif;

CIBlockElement::SetPropertyValuesEx (
  $arFields['ID'],$arFields['IBLOCK_ID'],array (
    'ATT_TEST' => $setProperty
   )
);
}
?>

Авторизация

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