Git: изменение авторства коммитов
В продолжение предыдущей заметки о миграции из SVN.
Имеющийся репозиторий крутился под управлением Visual SVN Server и всем сотрудникам почему-то были выданы уродские логины вида Ivan_Petrov, не учитывавшие, к тому же, e-mail автора.
При переносе истории изменений в Git с той же командой можно немного схитрить, изменив авторство коммитов при помощи вот такого шелл-скрипта:
#!/bin/sh
git filter-branch --force --env-filter '
an="$GIT_AUTHOR_NAME" # автор коммита
am="$GIT_AUTHOR_EMAIL" # e-mail автора коммита
cn="$GIT_COMMITTER_NAME" # коммитер
cm="$GIT_COMMITTER_EMAIL" # e-mail коммитера
if [ "$GIT_AUTHOR_NAME" = "Ivan_Petrov" ]
then
cn="Ivan Petrov"
cm="ivan@petrov.com"
an="Ivan Petrov"
am="ivan@petrov.com"
fi
export GIT_AUTHOR_NAME="$an"
export GIT_AUTHOR_EMAIL="$am"
export GIT_COMMITTER_NAME="$cn"
export GIT_COMMITTER_EMAIL="$cm"
'
На что нужно обратить внимание:
- ключ
--force, который может потребоваться, если историю репозитория уже переписывали (см. пост про смену корневой папки) - переменные
cn,cm,an,am. В небольших коллективах автор коммита и коммитер может являться одним и тем же человеком, в больших проектах коммитить может специалист с определенными полномочиями, в то время как авторство кода может принадлежать другому программисту. if-then-блоков может быть неограниченное количество, хватит на всех членов команды- для проверки авторства доступна переменная
$GIT_AUTHOR_EMAIL
Git: Сделать подкаталог репозитория корневым
Ситуация — жил-был SVN-репозиторий, в котором одновременно велась история двух частей проекта, условно клиентской и серверной. То есть — две папки, client и server.
При переходе к Git SVN-репозиторий, несмотря на попытку чекаута отдельной папки, выдергивает весь проект целиком, включая историю изменений.
В то же время, нам, по уму, теперь хочется иметь два отдельных репозитория на клиент и на серверную часть. Что делать?
Решение в лоб — сделать две копии Git-репозитория, и в каждой:
$ rm -rf server$ git add .$ git commit
Решение правильное:
$ git filter-branch --subdirectory-filter client HEADRewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (199/199)Ref 'refs/heads/master' was rewritten
Результатом работы станет переписанная история, из которой будут удалены все ссылки на папку server и объекты в ней.
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
Однако пользоваться этой командой, предназначенной для крайних случаев, следует с осторожностью и по возможности в отдельной ветке.
Источник: ProGitПо теме
Yii + Bitrix
Нашел хороший, но неполный рецепт по склейке Yii и 1С-Битрикс. На этот раз захотелось мне из Yii-приложения лазить в базу через Bitrix API, однако вылезает фундаментальная проблема — конфликт имен классов (пространства имен не используются). Решение: в PhpStorm прогоняем по папке с фреймворком Yii функцию Replace in path (case sensitive, whole words only) для следующих пар слов:
После этого меняем имена файлов:CComponent → YiiComponentCEvent → YiiEventCModule → YiiModuleCApplication → YiiApplicationCMenu → YiiMenu
Соответственно, если в приложении есть вызовы компонентов по старым именам (// в папке baseCComponent.php → YiiComponent.phpCModule.php → YiiModule.phpCApplication.php → YiiApplication.php// в папке zii/widgetsCMenu.php → YiiMenu.php
$this->widget('zii.widget.CMenu')) — нужно все переименовать.
Дописываем в index.php:
Как пользоваться:// ..require_once($yii);// наш кодfunction __autoload($className){// подключаем файлы битрикса через автозагрузкуinclude_once('../bitrix/modules/main/include/prolog_before.php');CModule::RequireAutoloadClass($className);}define("NO_BITRIX_AUTOLOAD", FALSE);// сначала отключим автозагрузчик Yii, потом, после Битрикса, включим обратноspl_autoload_unregister(array('YiiBase','autoload'));spl_autoload_register('__autoload');spl_autoload_register(array('YiiBase','autoload'));// закончилиYii::createWebApplication($config)->run();
public function actionFoobar()
{
if(CModule::IncludeModule('iblock'))
{
// если подключился модуль информационных блоков, можно работать...
}
}
TODO: Разобраться, возможно, получится повесить prolog_before.php и prolog_after.php на события onBeginRequest и onEndRequest.
Yii: хитрые ячейки в CGridView
Понадобилось мне компоновать значения некоторых полей модели при выводе в гридвью. Решение достаточно элегантное:
<?php
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $dataProvider,
'columns' => array(
array(
'header'=>'Хитрая колонка',
'value'=>'$this->grid->getOwner()->renderPartial(\'cells/_myCustomCell\', array(\'data\'=>$data),true',
'type'=>'raw',
),
),
Как это работает
В папке с вьюшками контроллера, который выводит гридвью на экран создаем папку cells, а в ней по желанию файлы вьюшек (в нашем случае это _myCustomCell), где данные модели доступны через переменную $data (а не $model, что важно). После этого в коде объявления колонки мы указываем значение, и выводим «сырое» ('type'=>'raw') представление данных — то есть голый неэкранированный HTML из вьюшки.
По теме:
Yii: MySQL bit и его проблемы
При разработке проекта столкнулся с проблемой — для поля типа bit в MySQL-базе данных не получалось вывести его реальное значение в Yii. Вместо нуля или единицы приходил нечитаемый символ, отображающийся квадратиком. Изначально я хотел использовать поле для чекбоксов, но естественно, с такой проблемой они не заработали.
Оказалось, проблема не столько в Yii, сколько в самом MySQL, где bit является плохо работающим костылем. Так что лучше по старинке, использовать tinyint(1)
Yii: сохраняем незаполненные поля формы как NULL
В модели прописываем правило:
protected function rules()
{
return array(
...
array('yourField, yourField2', 'default', 'setOnEmpty' => true),
...
);
}
Все!
Radio buttons
На днях в рассылке localize.drupal.org был задан вопрос о том, как переводить «radio button». Radio button, если что, это элемент пользовательского интерфейса, позволяющий сделать единственный выбор между несколькими заранее заданными опциями.
Вопрос, на самом деле, очень правильный. Сам я с радио баттонами работаю уже много лет (девятый пошел, что ли), но никогда особенно не задумывлся об этимологии этого названия. Причем радио баттоны эти вроде и не баттоны вовсе (не нажимаются ведь) да и радио тут причем?
Оказывается, в названии отражена аналогия сути. Когда-то давно в машинах радио имело кнопки, переключающие станции. При нажатии на одну из кнопок, остальные выскакивали, и таким образом одновременно выбрать можно было лишь одну.

Yii: как избавиться от index.php
Первое, что хочется изменить под себя, когда начинаешь разработку на Yii: отключить показ index.php в адресах.

Странно, что такое поведение включено в стандартную поставку.
Решение довольно простое.
Первое, что нужно сделать, это изменить в конфигурационном файле секцию urlManager:
'urlManager'=>array(
'urlFormat'=>'path',
// добавляем нижеследующую строчку
'showScriptName'=>false,
'rules'=>array(
'post//'=>'post/view',
'posts/'=>'post/index',
'/'=>'/',
),
),
Второй шаг — надо создать файл .htaccess (еще одна странность стандартной поставки):
RewriteEngine on
# если файл или директория существуют, отдать их напрямую
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# в противном случае вызвать index.php
RewriteRule . index.php
Готово!
Еще по теме:
Правильные кнопки

Очень часто разработчики ленятся погуглить, чтобы найти хорошую технику вообще для чего угодно. Даже банальная задача скруглить у кнопки уголки порой удивляет изобретательностью автора.
Плохой пример: кнопка на картинке выше состоит из «спрайта» и вот такого кода:
<input type="submit" class="submit" onclick="App.interestsFormSubmit()" value="" id="submit" name="submit" style="background-position: 0px 0px; ">
Здесь две ошибки. Первая ошибка — не прописан value у инпута. Это значит, что кнопка как минимум без текста, как максимум браузер туда подставит свое дефолтное значение вроде «Отправить данные», если вдруг стили не подгрузятся, или их заменят на другие.
Вторая ошибка — опрометчивое использования текста-картинки в качества замены value фоном.
Третья, (не)ошибка, но не устраивающая меня вещь — в принципе неуниверсальное решение, которое начнет приносить проблемы, если размер текста на кнопке или его длина внезапно поменяются. Иначе говоря — кнопка не резиновая.
Наткнулся на такой дурной код я тогда, когда понадобилось сайт перевести один на английский язык. Если с текстами Zend Framework и $this->view->translate() еще справлялись, то вот с таким чудом техники придется расчехлять фотошоп и ковырять PSD.
Как бы там ни было, для решения проблем и просто по теме советую две статьи Сергея Чикуенка:
Создание региональных версий сайта, часть первая. Шаблоны

По работе мне приходится поддерживать и развивать сайт крупной компании, имеющей представительства в разных регионах России.
Со временем сайт начал разрастаться все больше и больше, да еще и надзорная организация заставила делать подсайты для каждого из регионов, в котором оказываются услуги.
Ситуация несколько усложняется тем, что для этих регионов шаблоны сайта немного различаются, но в то же время, в большинстве своем похожи и используют одни и те же стили, скрипты, разметку.
Сейчас подсайтов два, а что, если завтра будет три, четыре, десять? Не копипастить же одно и то же.
После пары недель размышлений пришел к вот такому варианту. Подозреваю, что изобрел велосипед, и может быть в каком-нибудь приличном шаблонизаторе это уже придумано, но у нас Битрикс, детка, и в качестве шаблонизатора там собственно PHP, что, в принципе, очень ок. По крайней мере это дает известную свободу — имея на руках header.php и footer.php можно внутри них делать что душа пожелает.
Итак, сначала шаблон необходимо разбить на логические блоки. Шапка, тело, подвал, сайдбары, в сайдбарах отдельные блоки (поиск, обратная связь, и т.п).
Структура папок для всего этого такая:
|---includes
| |---templates
| | |---blocks
| | | |---rb
| | | |---moscow
Таким образом, на каждый блок надо иметь как минимум один файл имяблока.php, который будет лежать в папке дефолтного региона, и будет общим для всех. Если блок для показа в другом регионе нужно изменить, надо иметь в подпапках соответствующие копии.
За показ блока в шаблоне отвечает другая функция:
function renderBlock($block, $region_specific = false) {
$include_path = $_SERVER['DOCUMENT_ROOT'].'/includes/templates/blocks/';
// если блок регионозависим — подключаем из другой папки
if($region_specific == true)
{
$include_path .= detectRegion();
}
else
{
$include_path .= 'rb';
}
$include_path .= '/'.$block.'.php';
// вставляем
require_once($include_path);
}
В шаблоне блок вызывается вот так, например:
<?
renderBlock('feedback');
?>
Если функцию вызвать со вторым параметром, установленным в true, будет подключен файл для конкретного региона.
Кстати о регионах. В моем случае определение региона посетителя происходит после ручного выбора города на сайте через <select>, поэтому примитивная функция считывает информацию из куков:
function detectRegion() {
// в любой момент функцию можно усложнить по ситуации
// но мне пока и так хватает :)
if($_COOKIE['city'] == 'moscow')
{
return 'moscow';
}
else
{
return 'rb';
}
}
Таким образом, каждый шаблон представляет собой последовательность подключенных файлов-блоков, где в любой момент можно включить «регионозависимость».
Пока вроде работает, посмотрим, как зарекомендует себя со временем.
P.S. При виде вышеописанного почему-то в памяти всплывают регионы и блоки Друпала, но какая теперь разница :)
Подсветка синтаксиса в Tumblr
Сразу встала необходимость подсвечивать куски кода, которые я сюда собрался выкладывать, поэтому озадачился решением.
Решение оказалось простым и элегантным!
Идем в Customize appearance, в настройках темы включаем Custom HTML, тема предстает перед нами в виде исходника. Код из поста по ссылке советую разделить — скрипты вставить перед </body>, а стили подключить перед стилями темы в хедере, тогда можно их переопределить. Например я сразу прописал
pre.prettyprint {
border:0;
padding:1em;
}
и все стало довольно симпатично.
Привет всем.
Тут, пожалуй, будет мой вебдев-бложик, вдали от уютной жежешки.
