суббота, 23 декабря 2017 г.

Алгоритм вращения массива

В одном из заданий на сайте codewars в качестве дополнительного алгоритма требовалось вращать массив в конкретном направлении.

Хотя направлений всего два (против или по часовой стрелке), приведу вам код для вращения против часовой стрелки.
Итак, исходные данные:
$a = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
];

Требуется получить:
$a = [
    [3,6,9],
    [2,5,8],
    [1,4,7],
];

понедельник, 14 августа 2017 г.

Очистка сессий в битриксе

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

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

Для начала изучим код метода, разлогинивающего пользователя.
Как видно, в методе Битрикс уничтожает только собой же установленный массив данных SESS_AUTH и еще несколько ключей.
Остальные данные остаются в сессии и умирают спустя некоторое время после закрытия браузера.
Значит, требуется удалить эти данные самостоятельно.
В коде того же метода видим, что в ходе его работы возникают несколько событий, на которые можно повесить обработчик.
Выбираем, к примеру, событие OnAfterUserLogout и вешаем на него собственный обработчик, в котором удаляем сессионные данные. Например, так:

// Регистрация обработчика
AddEventHandler(
    'main',
    'OnAfterUserLogout',
    ['Some\Namespace\Here\EventHandlers', 'deleteSessionData']
);

// Собственно обработчик
public function deleteSessionData()
{
    unset($_SESSION['CUSTOM_SESSION_KEY']);

    // Явно вернем true чтобы не испытывать проблем с трактовкой результата
    return true;
}

После этого можно спать спокойно.

P.S. Как вариант, можно добавлять свои данные в ключ SESS_AUTH и тогда событие не понадобится совсем. Однако, в этом случае следует быть внимательным в выборе названия ключей, чтобы ваши данные не затерли битриксовые или наоборот.

пятница, 11 августа 2017 г.

Модификация сообщения к коммиту

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

Если Редмайна у вас нет или интеграция с ним не настроена, можно своими силами сделать нечто похожее. Для это нам понадобится гит-хук commit-msg.

Находим его в папке .git/hooks проекта, ставим права на исполнение и заносим в него следующий код:

#!/bin/bash

# Получаем текст коммита из файла `.git/COMMIT_EDITMSG`
INPUT_FILE=$(cat $1)

# Создаем шаблон урла для редмайна или прочего трекера
# Не забываем экранировать слеши, так как данный шаблон
# будет как есть подставлен в регулярное выражение
rePattern='https:\/\/redmine.somedomain.com\/issues\/'

# C помощью sed заменяем последовательность
# вида #ЦИФРЫ (например #212) на ссылку в трекер
# вида https://redmine.somedomain.com/issues/212
INPUT_FILE=$(sed -re "s/#([0-9]+)/${rePattern}\1/g" <<< "$INPUT_FILE")
# Перезаписываем файл `.git/COMMIT_EDITMSG` новым текстом
echo "$INPUT_FILE" > $1

exit 0


Ссылка на gist.

суббота, 1 июля 2017 г.

Число дней в месяце

В качестве короткого вечернего поста - задачка как получить число дней в произвольном месяце произвольного года.

Известно, что за число дней отвечает символ t в первом параметре функции date. Значит, остается правильно сформировать второй параметр и обернуть всё это в функцию, например, так:

function getDaysCount($month, $year)
{
    return date('t', strtotime('01.' . $month . '.' . $year));
}


Естественно, следует отметить, что формат d.m.Y являет собой дату в формате, понимаемом функцией date.

Тестовый прогончик:

$year = 2016;
foreach (range(1,12) as $month) {
    var_dump(getDaysCount($month, $year));
}

вторник, 20 июня 2017 г.

Кодировка для DOMDocument

Сегодня покажу вам, ребята, немного "костыликов" при работе с xml и xpath.

Допустим, откуда-то издалека вы получаете кусок html-разметки и дальше ее парсите, вытягивая заголовки, какие-нибудь абзацы текстов и прочие слова. Как только вы все полученные данные захотите вывести - может произойти так что на странице вместо текста будут всем известные кракозябры. В чем же дело? А дело в том, что при создании объекта DOMDocument вы не указали кодировку, в которой пришли данные. Ну и так как вы это не указали, то DOMDocument подумал, что данные пришли скорее всего в ISO-8859-1.

Само собой это надо быстренько исправить. И написать вот так:

// Создаем объект
$dom = new DOMDocument('1.0', 'utf-8');

// Ваша строка с HTML-разметкой
$stringToParse = "......";

// Загружаем строку в DOMDocument, ЯВНО указывая ее кодировку
$dom->loadHTML('<?xml encoding="utf-8"?>' . $stringToParse);

// Делаем xpath-запрос, например
$xpath = new DOMXPath($dom);
$ps = $xpath->query('//p');

Причем абсолютно неважно как выглядит строка с html-разметкой - один ли там корневой элемент или несколько, DOMDocument сделает все как надо.

понедельник, 10 апреля 2017 г.

Поиск по нестандартным элементам

Сегодня, друзья, я расскажу вам о том, как добавить в стандартный битриксовый поиск возможность искать по нестандартным элементам.
Стандартный битриксовый поиск это тот который bitrix:search.page. А нестандартные элементы - это, например, веб-формы. Или вообще какой-нибудь контент, который вы в своем, лично вами разработанном модуле, храните в отдельной таблице в БД.

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

суббота, 28 января 2017 г.

Замена пробелов табами и наоборот

Следуя PSR, мой редактор настроен на работу с отступами в 4 пробела, эта настройка применяется при открытии/сохранении файла, заменяя все лишние табы на пробелы.
Однако бывает так что некоторые файлы проекта обязаны иметь в качестве отступов табы. Так как мне лень ковыряться в настройках редактора и вводить какие-нибудь исключения-шмисключения, я сделал себе такой воркфлоу:
  • открываю нужный файл в редакторе
  • редактирую
  • сохраняю
  • командой unexpand заменяю пробелы на табы обратно.
Собственно, сегодня речь пойдет о командах unexpand и expand.

среда, 11 января 2017 г.

Отмена коммита в git

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

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

Я перебрал довольно много вариантов получения разницы между ветками и остановился на команде

git rev-list HEAD..origin/branch --count

Выводом данной команды является число коммитов, на которое локальная ветка отличается от ветки в удаленном репозитории. Если ветки одинаковы - то это число 0. Если ветки в удаленном репозитории нет - то возвращается пустая строка и дополнительное сообщение о том что ветка origin/branch не найдена в удаленном репозитории.

суббота, 7 января 2017 г.

Команды MySQL

После того как вы освоили простецкие команды mysql типа
SELECT * FROM
или
UPDATE `TABLE` SET ...
то можно изучить новые, ранее неизвестные, дабы лучше понимать что и как в вашей базе данных организовано.