Уже достаточно давно в свободное время внедряю в рабочие процессы фреймворк Laravel 5. Свободного времени обычно очень мало, но дело потихонечку движется. В данной заметке я покажу, как на этом самом Laravel 5 реализовать систему регистрации через инвайты (сиречь приглашения). То есть, когда с инвайтом регистрироваться можно, а без инвайта — нельзя.
Программирование
Модальное диаложество в AngularJS
Диалоговое окно — важный элемент в интерфейсах многих приложений. В этой заметке мы посмотрим, как в AngularJS вызвать модальный диалог, передать в него данные и получить результат (то есть действие пользователя) на примере бутстрапных диалогов Modal из ui.bootstrap (по ссылке есть примеры).

Микросовет банальный, про Views
Держите свои вьюхи в коде. Хук hook_views_default_views() — ваш лучший друг при работе с Views. Как только представление обрело нужные очертания — в код его, в код. Это легко, приятно и помогает от головных болей.
AngularJS и $scope.$apply()
If you’ve written a non-trivial amount of code in AngularJS, you may have come across the $scope.$apply() method. On the surface, it may seem like just a method you call to get your bindings to update. But why does it exist? And when do you need to use it?
To really understand when to use $apply, it’s good to know exactly why we need to use it, so let’s dive in!
AngularJS and scope.$apply
Отличные разъяснения.
Laravel и AngularJS
Изучаю всякое про прогрессивные технологии. Нашел вот туториал, не сохранить невозможно — хорошо и доходчиво излагает человек.
Create a Laravel and Angular Single Page Comment Application
Почитать про Drupal 8
Drupal 8 in 2 Steps — примеры базовых вещей (создать страницу, переменную, темизировать что-то).
Changes in the Form API in Drupal 8 — об изменениях в Form API.
Drupal 8: Ajax in Forms — небольшой пример с аяксификацией формы.
Responding to Events in Drupal 8 — о событиях в Drupal 8 с шутками и Бэтменом.
Exploring the Cache API in Drupal 8 — про Cache API с простыми примерами.
Install Drush 7 for Drupal 8 without throwing away Drush 6 — памятка как поставить drush 7 рядом с drush 6.
Всё на английском.
Немного динамического раутинга в Drupal 7
В Друпале, как известно, адреса основных сущностей, таких как пользователи и материалы, имеют вид user/123 и node/123 соответственно (где 123 — это id сущности). Если мы хотим, например, сделать страницу со всеми фотографиями для каждого пользователя, то скорее всего мы сделаем ее с адресом вроде user/123/photos. Ну потому что надо же откуда-то id пользователя взять и загрузить все его фотографии. И этот адрес будет хорош всем кроме одного — пользователю непонятно, почему он, Василий Петрович Пупкин, называется «123». Пользователю конечно было бы удобнее видеть свои фотографии по адресу vasya/photos. То есть неплохо было бы решить проблему ЧПУ.
Обычно (для отдельных страниц) в Друпале эта проблема решается с помощью синонимов (path aliases), то есть каждой странице (user/123) ставится в соответствие уникальный адрес (vasya), и страница /user/123 становится доступной по адресу /vasya. А чтобы избежать дубликатов страниц (т.е. одинаковых страниц с разными адресами), делается автоматический редирект с оригинальной страницы на ее синоним: при заходе на страницу user/123 пользователя перенаправляет на страницу /vasya.
Однако в случае когда страница динамическая (все фотографии данного пользователя) — получается, что нужно для каждой страницы вида user/{uid}/photos завести свой синоним. И обновлять его, если обновится синоним для страницы пользователя. И удалять, если пользователь удалится. И добавлять, если пользователь добавится. В общем, мало того, что для каждого пользователя нам придется не один, а два синонима хранить. Так нам еще и CRUD для синонимов поддерживать понадобится. А что если мы хотим еще страницу с блогами пользователя, страницу с его друзьями? Или вообще, мы хотим страницу архива материалов адресом вида user/123/archive/2014/09?
Entity API и пустое значение поля
Наверное, самая раздражающая вещь в Entity API изложена вот в этом комменте.
The problem is that you must set an empty value that is compatible with the data type of your field. If you do not, you will get an exception raised. Passing NULL or array() when a string is expected will therefore raise an error.
Another thing to keep in mind is that the data you pass will also depend on whether your field is a single value, a multi value field, or a field with multiple properties.
Пишешь себе, пишешь универсальный код с кучей разнородный полей, и вдруг вместо единообразного сброса поля хренак — и вылезает кучка дополнительных ветвлений.
Кстати, в комменте не сказано, но если по страшному стечению обстоятельств сбрасываемое поле помечено как required — это тоже будет неизбежное исключение.
CasperJS и Drupal
Сегодня мы немного поразбираемся в библиотеке CasperJS. Что такое CasperJS? Аннотация на сайте говорит нам, что это navigation scripting & testing utility, то есть инструмент для написания сценариев навигации и для тестирования. Работает CasperJS с помощью безбашенного headless-браузера PhantomJS (Webkit), либо с помощью почти-headless-браузера SlimerJS (Gecko).
Так что же с помощью CasperJS можно сделать? Например, можно написать вот такой скрипт:
casper.test.begin('Testing my website', function suite(test) {
casper.start();
casper.thenOpen('http://mytestsite.ru', function() {
test.assertHttpStatus(200, 'Homepage was loaded successfully.');
test.assertExists('div#logo', 'Header link to the homepage is present.');
test.assertExists('form#user-login-form', 'Login form is present.');
});
casper.run(function() {
test.done();
});
});
Этот скрипт автоматически зайдет на главную страницу заданного сайта и проверит, что http-response равен 200, а затем проверит, что на странице присутствует div с логотипом и форма логина.
User login block на продвинутых костылях
Как известно, всеми любимый блок логина в Друпале не появляется на страницах регистрации и восстановления пароля (user/register и user/password соотвественно). Объясняется это бессмысленное, на мой взгляд, ограничение обычным usability. В коде user.module, в котором оно реализовано, так и написано:
(это функция user_block_view)
Написано, правда, про то что не надо показывать две формы логина на одной странице, но паровозом к этому цепляется и регистрация с восстановлением.
// For usability's sake, avoid showing two login forms on one page.
if (!$user->uid && !(arg(0) == 'user' && !is_numeric(arg(1)))) {
$block['subject'] = t('User login');
$block['content'] = drupal_get_form('user_login_block');
}
А что если бы мы хотели избавиться от ограничения? Придется добавить немного костылей.
Противникам патчей ядра дальше читать не нужно.
