<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0" xml:base="https://graker.ru/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Друпальчики</title>
    <link>https://graker.ru/</link>
    <description>RSS домовой страницы</description>
    <language>ru</language>
    
    <item>
  <title>Возвращение к истокам произошло</title>
  <link>https://graker.ru/news/2026/10/29/vozvrashchenie-k-istokam-proizoshlo</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Свершилось то, о чем так &lt;a href=&quot;/news/2025/11/28/back-to-roots&quot;&gt;долго говорили&lt;/a&gt; большевики. Моя домовая страница переехала на Drupal 11! И, надо заметить, года все-таки не прошло.&lt;/p&gt;&lt;p&gt;Это окончательная точка в затянувшемся эксперименте с OctoberCMS: остальные лендосы я перевёл на статику (просто html). Потому что каждый с выходом уязвимости в PHP нужно было мощно обновлять, и ну его на фиг.&lt;/p&gt;&lt;p&gt;По ходу переезда домовая страница получила плюшки, которые я давно хотел добавить, например:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;заметки в бложеке сделал на параграфах, и это самое клёвое. Теперь можно втыкать в середину поста что угодно, например тизеры всякие. На следующем обзоре сериальчиков испытаю.&lt;/li&gt;&lt;li&gt;галереи можно смотреть целиком в лайтбоксе, независимо от пагинации.&lt;/li&gt;&lt;li&gt;всякое сео-гео-шмео и микроразметка стали гораздо лучше (во всяком случае, полнее).&lt;/li&gt;&lt;li&gt;поиск на search api куда круче того, что в октобере был.&lt;/li&gt;&lt;li&gt;админка на gin, reorder фоток в альбомах, апгрейд бутстрапа с 3 до 5 и много разных удобных мелочей.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Единственное, что в Октобере мне нравилось больше — это маркдаун-редактор, в который удобно втыкать тексты из Обсидиана. Наверно сделаю себе такой же.&lt;/p&gt;&lt;p&gt;А ещё теперь у домовой страницы есть английская версия. Не знаю, сильно ли она пригодится, но это прикольно и я давно хотел. Клод кстати под моей редакцией неплохо так переводит, и даже шутейки сам старается сохранять. Уже полсотни заметок перевели с ним, постепенно, потихонечку, добавим ещё. Хотя вряд ли всё до 2009 года будем, конечно.&lt;/p&gt;&lt;p&gt;Вообще конечно Клод Код тут оказался чистой магией под кончиками пальцев. Не только хорошо собрал на Друпале то, что задано — он еще и парсер для импорта материалов написал так, чтобы сразу по параграфам раскладывать, и медиа тоже импортнул с разделением на типы, как надо, и focal point поставил. До кучи написал юнит-тесты на кастомный код и визуальные регрессии на BackstopJS, чтобы проверять как дизайн перенёсся.&lt;/p&gt;&lt;p&gt;Тут дело (помимо качества самого Клода, естественно) в двух вещах:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;У Друпала огромная инфраструктура и сообщество. Масса материалов, примеров, кода, практик. Через это Claude Code очень хорошо умеет в Drupal.&lt;/li&gt;&lt;li&gt;У меня несколько проектов на D11 сделанных уже есть. Соответственно, есть наработки, чеклисты, джентльменский набор модулей и практик. Клоду можно это показывать — и он сразу сделает как мне нравится.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;PageSpeed на десктопе после переезда показывает вот чего:&lt;/p&gt;&lt;/div&gt;
&lt;figure data-component-id=&quot;grakerru:figure&quot; class=&quot;figure figure--center figure--medium&quot;&gt;
      &lt;a href=&quot;/sites/default/files/images/2026-10/pagespeed_grakerru.png&quot; data-lightbox=&quot;node-2273&quot;&gt;
    &lt;img loading=&quot;lazy&quot; srcset=&quot;/sites/default/files/styles/content_medium/public/images/2026-10/pagespeed_grakerru.png.webp?itok=FqxfTxi1 850w, /sites/default/files/styles/content_medium_2x/public/images/2026-10/pagespeed_grakerru.png.webp?itok=pAV67TpH 1507w&quot; sizes=&quot;(min-width: 1200px) 850px, (min-width: 768px) 75vw, calc(100vw - 30px)&quot; width=&quot;850&quot; height=&quot;914&quot; src=&quot;/sites/default/files/styles/content_medium/public/images/2026-10/pagespeed_grakerru.png.webp?itok=FqxfTxi1&quot; alt=&quot;Pagespeed for graker.ru&quot; /&gt;



&lt;/a&gt;
    &lt;/figure&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Сильно круче, чем было. У мобилок перформанс немного похуже, но победим и это.&lt;/p&gt;&lt;p&gt;Оформление сразу обновлять не стал, а то еще год бы обновлялся. Но оно тоже почти готово. Прогрессивный модуль Canvas тоже не стал ставить, но после редизайна наверно поставлю.&lt;/p&gt;&lt;p&gt;Заодно я кстати переехал в селектель, заменив последнюю копию надоевшей панельки ispmanager на traefik + docker compose окружение. Но про это в другой раз.&lt;/p&gt;&lt;p&gt;В общем, крайне доволен. Теперь надо доделать новый сайтик студии и заживём!&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Thu, 29 Oct 2026 09:30:00 +0000</pubDate>
    <dc:creator>graker_editor</dc:creator>
    <guid isPermaLink="false">2273 at https://graker.ru</guid>
    </item>
<item>
  <title>Нейросети и анализ кода</title>
  <link>https://graker.ru/news/2026/07/22/ai-code-analysis</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Вчера считал эстимейты на группу из ~40 тикетов. Все сделаны по отчету ИИ об анализе кода большого проекта на Drupal. Проекту около 10 лет, кодовая база развивалась все это время, 20 поддоменов, интеграции, апишки, синхронизация контента, в общем прикольный проект.&lt;/p&gt;
&lt;p&gt;Отчет структурированный, нейросеть проверяла всех четырёх всадников попокалипсиса в проекте: Уязвимости, Баги, Тормоза и Грязный код. Изначально из переданного отчета получалось гораздо больше задач, но процентов на 30% я сразу won&#039;t fix навесил. Там и глюки нашлись, и непонимание контекста. Но 40 тикетов тем не менее осталось.&lt;/p&gt;
&lt;p&gt;Среди них тоже в основном таски с минимальнейшим приоритетом, типа&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;в кастомном модуле не проставлена зависимость от чего-нибудь типа paragraphs;&lt;/li&gt;
&lt;li&gt;где-то в коде наглый программист вызвал \Drupal::service() вместо инъекции зависимостей;&lt;/li&gt;
&lt;li&gt;где-то deprecated-версии Друпала не убраны из поддерживаемых версий и тому подобное.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Нашлось и несколько более серьезных претензий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;парочка проблем N+1;&lt;/li&gt;
&lt;li&gt;несколько XSS-уязвимостей (доступных только админам, но всё же);&lt;/li&gt;
&lt;li&gt;несколько мест, где отсутствуют проверки на наличие ключа в массиве (спамит в лог предупрежденими);&lt;/li&gt;
&lt;li&gt;и даже одна уязвимость типа timing oracle.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Да, грязненький код — признак грязненьких мыслей :) Да, хорошо бы всё это почистить. Но за вычетом 3–4 претензий, это получается больше ста часов работы суммарно, а выхлоп — немножко более чистый код, причёсанное legacy, немножко меньше техдолга и warning/debug-записей в логе. Хорошо конечно, когда заказчик не против провести такую генеральную уборку. И честь и хвала аккаунтам, которые могут убедить заказчика в необходимости такой уборки при примерно нулевой ценности для конечного пользователя.&lt;/p&gt;
&lt;p&gt;А ощущения от таких отчетов по-прежнему странные. Вроде и находит что-то. Но суеты с этими отчетами пока куда больше, чем пользы.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Wed, 22 Jul 2026 09:15:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2227 at https://graker.ru</guid>
    </item>
<item>
  <title>Критичное обновление безопасности в Drupal</title>
  <link>https://graker.ru/news/2026/05/19/drupal-highly-critical-update</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Как понять, что у какого-то проекта клёвая инфраструктура?&lt;/p&gt;
&lt;p&gt;Ты прочитал письмо в рассылке, что у проекта через несколько дней выйдет обновление безопасности. Добавил в календарь, чтоб не забыть обновить всё и всех. Потом получил письмо СРОЧНО ВАЖНО от одного хостера. Потом от другого и третьего. Всё про это обновление безопасности.&lt;/p&gt;
&lt;p&gt;Потом прочитал напоминание в тематическом телеграм-канале. Потом ожили коллеги в джире, каждый тоже написал о будущем обновлении. Вслед за коллегами ожили клиенты: они тоже получили уведомления от своих хостеров и теперь переживают. В общем ВСЕ уже знают, что у Друпала завтра вечером выйдет патч безопасности. Все знают, все готовятся.&lt;/p&gt;
&lt;p&gt;Так что и я глаголю вам: да, завтра с 17 до 21 UTC должен выйти патч безопасности Drupal 10 и 11, вот &lt;a href=&quot;https://www.drupal.org/psa-2026-05-18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;страничка&lt;/a&gt; об этом. Обновление обозначено как высоко критичное, набрало 20 из 25 баллов по шкале трэша, угара и содомиии рисков безопасности. В воздухе запахло озоном, на теле заныли шрамы, полученные в ходе Друпалгеддона I и II.&lt;/p&gt;
&lt;p&gt;Обновляйтесь, друзья, как можно скорее — это нужно. А если вы хотите сначала посмотреть, чо там будет, ответственно заявляю: всегда лучше обновиться, и посмотреть, чо там будет с теми, кто не стал, чем наоборот ;)&lt;/p&gt;
&lt;p&gt;И да — вот такая клёвая инфраструктура сейчас у Drupal. Отдельная рассылка по обновлениям безопасности. Команда, которая этими дырками занимается. Проверки дырочек не только в ядре, но и в контрибных модулях. Патчи выкладываются в определенный день с предварительным уведомлением.&lt;/p&gt;
&lt;p&gt;И да — Drupal при этом совершенно бесплатный.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Tue, 19 May 2026 18:05:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2212 at https://graker.ru</guid>
    </item>
<item>
  <title>Как мы обновляем Drupal</title>
  <link>https://graker.ru/news/2026/02/08/how-we-do-drupal-updates</link>
  <description>&lt;p&gt;Год назад, в январе, окончательно наступил конец жизненного цикла Drupal 7. Однако заявки на обновление с «семерки» до актуальной версии появляются до сих пор. Как и в целом заявки на обновление Друпала. В связи с чем небольшой ликбез о том, как мы обновляем Drupal и&lt;/p&gt;
&lt;h4&gt;Зачем вообще что-то обновлять&lt;/h4&gt;
&lt;p&gt;Основных причин обновлять Drupal, как и другую CMS, как и программное обеспечение в общем, три:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Новый функционал. Разработчики добавили, выпустили обновления. Мы обновили, получили новые штучки.&lt;/li&gt;
&lt;li&gt;Исправление ошибок — программ без них, как известно, не бывает. Разработчики нашли баг, исправили, выпустили обновление. Мы обновили, получили более стабильное ПО.&lt;/li&gt;
&lt;li&gt;Обновления безопасности. В программах, с которыми можно работать через Интернет, регулярно находят уязвимости, то есть потенциальные точки взлома. Уязвимости бывают разными, одни позволяют увидеть информацию, к которой доступ ограничен, другие позволяют подготовить покражу пароля у пользователя, третьи — получить полный контроль над программой или вообще над сервером.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;И если без пунктов 1 и 2 в принципе можно жить, то пренебрегать обновлениями безопасности не следует. Дело в том, что сайты взламывают не только в кино, и не только какие-нибудь крупные, или известные. Со временем к найденным в ПО уязвимостям пишут сканеры и эксплойты — программы, которые автоматически находят сайты с незакрытыми уязвимостями и автоматически же их взламывают. А взломщику достаточно просто запустить эту программу — и вот у него уже доступ к вам на сервер.&lt;/p&gt;</description>
  <pubDate>Sun, 08 Feb 2026 06:30:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2190 at https://graker.ru</guid>
    </item>
<item>
  <title>Играюсь в Drupal Canvas</title>
  <link>https://graker.ru/news/2026/01/27/playing-with-drupal-canvas</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Играюсь с Canvas, новым визуальным конструктором страниц под Drupal, первая версия которого вышла в декабре. Вскоре должна получиться статья на тему, а может даже и видео — не решил еще. &lt;/p&gt;
&lt;p&gt;Пока вкратце:&lt;/p&gt;
&lt;p&gt;— прикольно;&lt;br&gt;
— польза от компонентной верстки / SDC / сторибуков и этого всего — возросла;&lt;br&gt;
— интеграция с остальной инфраструктурой Дру пока невысока;&lt;br&gt;
— есть конечно немного багов.&lt;br&gt;&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Tue, 27 Jan 2026 16:15:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2186 at https://graker.ru</guid>
    </item>
<item>
  <title>Happy birthday Drupal!</title>
  <link>https://graker.ru/news/2026/01/15/happy-birthday-drupal</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Официальный сайт &lt;a href=&quot;https://www.drupal.org/blog/drupal-turns-25-today&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;внезапно сообщил&lt;/a&gt;, что сегодня Друпалу стукнуло 25 лет! И это отличный повод предаться &lt;del&gt;старческому ворчанию&lt;/del&gt; воспоминаниям.&lt;/p&gt;
&lt;p&gt;Сам я прикоснулся к прекрасному примерно 20 лет назад. Трудился я тогда в микроэлектронике, зарплаты были небольшими, зато платили их довольно нестабильно. И все ребята искали способов подзаработать. Кто-то увольнялся в коммерческую разработку, кто-то открывал параллельно малую торговлю. &lt;/p&gt;
&lt;p&gt;Ну а я полез на веблансер искать заказы. Благо задержки зарплаты в несколько месяцев и работа рядом с домом позволяли иметь весьма свободный график. И там, на веблансере, я увидел проект шахматного портала. Сразу понял, что это знак судьбы! К шахматам я всегда относился трепетно, а незадолго до этого написал на c++ программку для игры по сети. Мы ее с товарищем яростно тестировали, мечтая устроить в зеленоградской сети локальный филиал Новых Васюков.&lt;/p&gt;
&lt;p&gt;Об этом я радостно сообщил заказчику проекта. Правда оказалось, что заказчик хотел портал на каком-то там Друпале, да и с веб-сайтами я до этого имел дело только пару раз. Но меня позвали, типа набираться опыта, и я пошёл. Кем-то вроде менеджера. Заработал целых 100 баксов и бутылку какого-то швейцарского вина.&lt;/p&gt;
&lt;p&gt;Но было круто! Мы нашли java-кодера, переписали с ним полезные части моего движка на php под сервер на Друпале, и сделали к нему клиентский джава-апплет для игры. &lt;/p&gt;
&lt;p&gt;А особенно круто было тестировать. Я позвал знакомого кмса, чтобы он меня по 10 раз в день выносил. Ну и иногда я его, разок в неделю.&lt;/p&gt;
&lt;p&gt;А дальше... дальше видимо сработал синдром утёнка. Шахматный портал не выжил, но Друпал остался ждать. &lt;/p&gt;
&lt;p&gt;Позже я увлёкся переводами и смастерил свой скрипт для коллективной работы. Решил построить портал для переводов на Друпале, параллельно завёл бложек и стал потихоньку писать про разработку. Что получается, что нет, как сделать то и это.&lt;/p&gt;
&lt;p&gt;Подтянулись интересные люди. В коммьюнити Drupal.ru нашёл их ещё больше. Некоторые из них кстати здесь с нами, в этой комнате. Здоровья вам и успехов, друзья и коллеги!&lt;/p&gt;
&lt;p&gt;Потом открыли студию, через бложек нашлись крутейшие заказы. Потом апворк, разработка международных проектов, тимлидство. Так я и стал Друпал-разработчиком. Практически случайно.&lt;/p&gt;
&lt;p&gt;Что тут скажешь. &lt;del&gt;Вот чего шахматы с людьми делают&lt;/del&gt; С днём рождения, Drupal! Many happy returns!&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Thu, 15 Jan 2026 20:25:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2183 at https://graker.ru</guid>
    </item>
<item>
  <title>Друпал жыв!</title>
  <link>https://graker.ru/news/2025/12/12/drupal-lives</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;В ходе нетворкинга общаюсь с разными людьми, тоже связанными с веб-разработкой. И конечно часто упоминаю Drupal, раз уж последние 20 лет чаще всего работаю с ним.  &lt;/p&gt;
&lt;p&gt;И довольно часто слышу в ответ что-то вроде: «Друпал? А он что, еще жив?»  &lt;/p&gt;
&lt;p&gt;Понять можно. Если человек сталкивался с ним когда-то давно, в начале 10х годов например, и тогда показалось что он не очень актуален, то сегодня-то тем более. Тогда Друпал критиковали за всякое — и за «отсутствие ООП», и излишнюю функциональность, и за принцип not invented here, и за сложность перехода от одной мажорной версии к другой. Хотя лично мне и D6, и D7 хорошо заходили.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это как встретить старого приятеля, которого не видел 20 лет. Сознание не очень-то интерполирует его «возможный жизненный путь» и не натягивает его на эти 20 лет. Поэтому может показаться, что он все такой же, как «тогда». А он уже не такой.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Вот и Друпал уже не такой. Правда, за эти годы он нажил не седину, геморрой и алименты. А наоборот — стал гораздо краше! В конце 2015-го с ним произошло лучшее, что могло произойти: вышла версия 8, в которой сделали:  &lt;/p&gt;
&lt;p&gt;— &lt;strong&gt;Конфиги на yaml&lt;/strong&gt;. То есть всё, что ты накликал в админке, лёгким движением руки выгружалось в файлики и автоматически разворачивалось в продакшне. Это упростило в разы не только разработку, но и поддержку: теперь можно легко увидеть, чего там клиент в настройках нажал и всё сломалось. Увидеть и отменить.&lt;/p&gt;
&lt;p&gt;— &lt;strong&gt;Установку и обновление всего через composer&lt;/strong&gt;. Апгрейд мажорных версий тоже упростили. Для перехода с 8 на 9, 10 и 11 переписывать сайт целиком уже необязательно.&lt;/p&gt;
&lt;p&gt;— Темизацию на Twig, медиа-библиотеку а ля Wordpress, поддержку REST для вывода контента в JSON/XML и получения headless CMS, и много чего ещё.&lt;/p&gt;
&lt;p&gt;— &lt;strong&gt;Отринули критикуемый многими принцип not invented here&lt;/strong&gt;, по которому не любо было тащить в ядро сторонние решения. Отринули и тут же затащили под капот Symfony.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это такой крутой фреймворк на PHP, на котором можно писать в три раза больше кода, чем в Laravel, зато он будет чистый и правильный.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Это сразу зарешало большинство претензий к несовременному коду и отсутствию ООП. Классов, объектов и паттернов теперь сколько угодно. И контроллеры есть, и роутинг, и внедрение зависимостей, и декораторы, и подписка на события. &lt;/p&gt;
&lt;p&gt;Ляпота, короче. «Свинья в помаде» (&lt;a href=&quot;/news/2012/08/16/svinya_v_pomade_vozvrashchaetsya_ili_zapylivshiisya_krizis&quot;&gt;для тех кто не помнит&lt;/a&gt;) превратилась в &lt;del&gt;прекрасную бабочку&lt;/del&gt; серьезный современный продукт. С высоким по-прежнему &lt;a href=&quot;https://habrastorage.org/r/w1560/storage2/699/b74/27d/699b7427da76e3f11618ba2dc565282c.jpg&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;порогом вхождения&lt;/a&gt; и с чувством полного удовлетворения от своей работы, если этот порог преодолеть.&lt;/p&gt;
&lt;p&gt;— Так что, да, Друпал жив! — глаголю я вам в ответ, дорогие друзья. И уж точно поживее многих.&lt;/p&gt;
&lt;p&gt;Да, в нашей стране ситуация с ним не очень удачная: всё вокруг поглотил 1С Битрикс. Хотя обидно не это, так бывает. Мне как разработчику обидно, что на то нет никаких &lt;em&gt;технических&lt;/em&gt; причин. Писал про это в статье &lt;a href=&quot;/news/2025/11/14/some-myths-on-choosing-between-cms-and-frameworks&quot;&gt;CMS vs Framework&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;При этом во всем остальном мире с Друпалом полный порядок. Серьёзные контентные сайты, крупные, со связанными поддоменами, университеты, e-com, государственные порталы — везде ему находится применение. Поработал с парой десятков проектов в Европе и США, за последние 7 лет 1 каталог перешел на &lt;del&gt;битрикс&lt;/del&gt; WordPress, 1 магазин на Shopify — в связи со сменой маркетинговых команд, которым на входе конечно надо всё переделать. Остальным всё круто, работают годами. Хотелось бы конечно и на нашем рынке с ним чаще работать.&lt;/p&gt;
&lt;p&gt;Но в этом году, кстати, стал замечать тут и там отдельные звоночки, когда ребята, которые раньше на Drupal даже не смотрели, внезапно стали интересоваться и даже чего-то хотеть. Жизнь-то налаживается!&lt;/p&gt;
&lt;p&gt;А ещё недавно &lt;a href=&quot;https://dri.es/drupal-canvas-1-0-released&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Canvas 1.0 вышел&lt;/a&gt;, визуальный конструктор лендосиков на Drupal. На днях мы с ним поиграем, посмотрим чего он может, а чего нет. Результаты будут тут, не переключайтесь.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Fri, 12 Dec 2025 11:10:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2176 at https://graker.ru</guid>
    </item>
<item>
  <title>Вернёмся к истокам</title>
  <link>https://graker.ru/news/2025/11/28/back-to-roots</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Обсуждал тут улучшения своих сайтиков с чатом жопотэ, дипсиком, перплексити и другими сказителями. Идей роботы озвучили очень много, и внезапно я понял, что нужно возвращаться к истокам: взять и переписать эту домовую страницу и &lt;a href=&quot;https://netspark.ru&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;лендинг студии&lt;/a&gt; обратно на &lt;del&gt;Turbo Pascal&lt;/del&gt; Друпал.&lt;/p&gt;
&lt;p&gt;Эксперимент с October CMS был по-своему прекрасен, узнал и сделал много нового, и CMS неплохая. Но ряд вещей, которые я хочу сделать, на Друпале сделать тупо в 2–3 раза быстрее.&lt;/p&gt;
&lt;p&gt;Перенести в принципе недолго, сделать всё на вьюзах, а шаблоны фронта в October уже сделаны на twig. Можно даже управиться к Новому году. Надо только понять, к какому.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Fri, 28 Nov 2025 14:20:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2173 at https://graker.ru</guid>
    </item>
<item>
  <title>О выборе между CMS и фреймворками и некоторых мифах этого выбора</title>
  <link>https://graker.ru/news/2025/11/14/some-myths-on-choosing-between-cms-and-frameworks</link>
  <description>&lt;p&gt;С каждым новым проектом в разработке и разработчикам, и порой заказчикам, приходится делать такой выбор. При этом часто можно услышать:&lt;/p&gt;
&lt;p&gt;— CMS только для несложных / шаблонных проектов;&lt;br&gt;
— если нужна нестандартная логика — поможет только фреймворк.&lt;/p&gt;
&lt;p&gt;Посмотрим, так ли это, всегда ли это так, а заодно рассмотрим несколько, возможно, странных, но настоящих мифов и возражений заказчиков.&lt;/p&gt;
&lt;blockquote&gt;CMS — Content Management System, система управления контентом. Популярные CMS — это Wordpress, Drupal, ModX, Joomla и, конечно же, 1С-Битрикс. В CMS предполагается наличие административного интерфейса и настроек.&lt;/blockquote&gt;
&lt;blockquote&gt;Фреймворк (framework) — это набор инструментов, библиотек и способов написания кода, который обычно не предполагает уже существующих настроек и конфигураций, а предполагает их программирование. Популярные фреймворки веб-разработки — это, например, Laravel, Symfony, Django, Yii, Ruby on Rails, Next.js.&lt;/blockquote&gt;</description>
  <pubDate>Fri, 14 Nov 2025 14:50:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2167 at https://graker.ru</guid>
    </item>
<item>
  <title>Кэш</title>
  <link>https://graker.ru/news/2025/10/08/cache</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Если бы не работа на европейских проектах с CMS Drupal, никогда бы и не узнал, что&lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;по-русски     — кэш
по-английски  — cache
по-французски — cache
по-испански   — caché
по-итальянски — cache
по-шведски    — cache
по-румынски   — cache
по-немецки    — Zwischenspeicher&lt;/code&gt;&lt;/pre&gt;
</description>
  <pubDate>Wed, 08 Oct 2025 13:40:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2152 at https://graker.ru</guid>
    </item>
<item>
  <title>Про разработку и поддержку магазина на Drupal 9</title>
  <link>https://graker.ru/news/2025/09/08/drupal-9-ecommerce-dev-and-support</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Как-то сделали мы крутой магазин на Drupal 9 американскому отделению известного бренда, называть который конечно же не следует.&lt;/p&gt;
&lt;p&gt;Импорт товаров, постоянная синхронизация складов, десяток видов доставки, трекинг, фасеты. Поиск и каталог на Apache Solr с кастомизированным индексом: заказчик хотел, чтобы некоторые атрибуты товара отображались в каталоге как отдельные позиции, а страница у товара была при этом одна.&lt;/p&gt;
&lt;p&gt;Пару лет поддерживали, до Drupal 10 поапгрейдили. А потом решил заказчик сменить всю маркетинговую команду, а команда, соответственно — субподрядчика по сайту, то есть разработчика.&lt;/p&gt;
&lt;p&gt;А потом новые подрядчики приходят и говорят — проконсультируете нас по коду, если что, расскажете чего зачем?&lt;/p&gt;
&lt;p&gt;Я говорю, конечно, завсегда, обращайтесь. А они через несколько дней такие — вы знаете, мы все изучили, и у вас так хорошо написано, всё понятно и без комментариев. &lt;/p&gt;
&lt;p&gt;И мне вроде досадно: увели, редиски, проект отличный. И в то же время гордость пробирает — не зря стало быть работаем, что несколько лет кода (много кода) могут люди потом разобрать и понять.&lt;/p&gt;
&lt;p&gt;Ведь закрыть задачу в трекере и закрыть задачу в трекере хорошо — это, как говорится, две большие разницы. И мы будем дальше стараться, свой ли проект, чужой, можно ли его всем показывать, или нельзя, или его потом вообще заберут. Такая наша работа.&lt;/p&gt;
&lt;p&gt;Думаю только — вот бы и нам такие проекты на поддержку передавали.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Mon, 08 Sep 2025 20:40:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2137 at https://graker.ru</guid>
    </item>
<item>
  <title>Деплои и удаление зависимостей</title>
  <link>https://graker.ru/news/2025/05/23/removing-dependencies-on-deploy</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Note to self: когда есть задача выключить из проекта тот или иной контриб-модуль, никогда не надо в этой же задаче требовать убрать сам код модуля из проекта. &lt;/p&gt;
&lt;p&gt;На примере Drupal и PHP: во всех деплой-скриптах, что мне доводилось видеть или писать, &lt;code&gt;composer install&lt;/code&gt; (установка/обновление/удаление зависимостей) всегда идет первее &lt;code&gt;drush updb&lt;/code&gt; (миграции БД) и &lt;code&gt;drush cim&lt;/code&gt; (импорт загруженной из гита конфигурации). И это разумно в большинстве случаев: сначала при деплое мы тянем из интернета новые зависимости, затем запускаем миграции БД, требуемые этими зависимостями, затем применяем конфиг для этих зависимостей, включая yml-файлы с настройками нового модуля. &lt;/p&gt;
&lt;p&gt;Однако при удалении модуля всё происходит наоборот: сначала нам нужно применить конфиг, в котором модуль «выключается» из системы, при этом будут удалены yml с его настройками, а также вызваны нужные обратные миграции БД. И только потом уже нам нужно вызвать &lt;code&gt;composer install&lt;/code&gt; чтобы композер заметил отсутствие модуля в зависимостях и удалил его из кода.&lt;/p&gt;
&lt;p&gt;Поэтому если мы единым мердж реквестом подадим отключение модуля (т.е. конфиг в котором модуль отключен) и удаление его из кодовой базы (удаление зависимости в &lt;code&gt;composer.json&lt;/code&gt; например), то результатом деплоя будет ошибка. Поскольку скрипт сначала удалит кодовую базу, а потом уже попытается выполнить &lt;em&gt;уже удаленный&lt;/em&gt; код, связанный с деинсталляцией. В результате деплой потребуется чинить вручную и тривиальная задача потребует времени в два раза больше нужного. Это как минимум, а если у нас скажем мультисайтинг с одной кодовой базы на 50 инстансов, вручную чинить уже не захочется.&lt;/p&gt;
&lt;p&gt;В общем, вместо требования удалить отключаемый модуль сразу из кодовой базы лучше время от времени создавать maintenance-задачу по удалению из списка зависимостей неиспользуемых &lt;em&gt;и уже ранее отключенных&lt;/em&gt; библиотек.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Fri, 23 May 2025 12:55:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2104 at https://graker.ru</guid>
    </item>
<item>
  <title>VS Code и Codeium</title>
  <link>https://graker.ru/news/2024/11/19/vs-code-and-codeium</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Перешел не так давно на VS Code &lt;a href=&quot;/news/2024/10/26/pro-phpstorm&quot;&gt;с phpstormа&lt;/a&gt;, работает неплохо, плагины есть, в целом доволен. А сегодня поставил &lt;a href=&quot;https://codeium.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Codeium&lt;/a&gt; — ИИ-плагин, чтобы вкалывали, значит, роботы, а не человек.&lt;/p&gt;
&lt;p&gt;Сначала говорю ему: — чат жопотэ, напиши чтобы я нажимал на иконку, а из неё плашка выпадала с уведомлениями!&lt;/p&gt;
&lt;p&gt;Он написал. И даже once не забыл, и переделывать почти не пришлось. Потом попросил сделать плашку белой, с синим скругленным бордером и тенью. 2 секунды, сделал, про position absolute сам догадался.&lt;/p&gt;
&lt;p&gt;Решил попробовать что-нибудь друпальное. Вот что я получил по промпту &lt;em&gt;Count workflow notifications where recipient is current user id and viewed is NULL&lt;/em&gt;.&lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;$query = $this-&amp;gt;entityTypeManager-&amp;gt;getStorage(&amp;#039;workflow_notification&amp;#039;)-&amp;gt;getQuery();
$count = $query
    -&amp;gt;condition(&amp;#039;recipient&amp;#039;, $this-&amp;gt;currentUser-&amp;gt;id())
    -&amp;gt;condition(&amp;#039;viewed&amp;#039;, NULL, &amp;#039;IS NULL&amp;#039;)
    -&amp;gt;count()
    -&amp;gt;execute();
return $count;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Никакой специальной подготовки, плагин сам все нужные Drupal API увидел. Просить просто «for current user, not viewed» не стал — забоялся. Причем не знаю, чего больше — что не поймет и придется второй раз вбивать, или что все равно поймет и сделает. Попросил сгенерировать к этому коду комментарий, оказалось, всё понимает:&lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt; /**
   * Count the number of workflow notifications that belong to the current user
   * and are unread.
   *
   * @return int
   *   The number of unread notifications.
   */&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;В целом этого достаточно уже, чтобы пользоваться повседневно. Как говорится, the future is here &lt;del&gt;this is how I disappear&lt;/del&gt;.&lt;/p&gt;
&lt;p&gt;Завтра заставлю роботов писать за меня юнит-тесты. А также нажму манящие кнопки Refactor и Explain рядом с кодом.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Tue, 19 Nov 2024 18:55:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2077 at https://graker.ru</guid>
    </item>
<item>
  <title>Хакаем Drupal правильно</title>
  <link>https://graker.ru/news/2020/09/11/hack-drupal-the-right-way</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;С переходом в Drupal 8 на composer запихивать контрибные модули и само ядро в git стало совсем не удобно и не правильно. Но хакать (точнее, делать лучше!) модули и ядро все равно хочется. К счастью, с композером это даже удобнее.&lt;/p&gt;
&lt;p&gt;Допустим, мы внесли изменения в модуль contrib_module и хотим их увековечить в своем гите. Действия следующие:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ставим пакет &lt;code&gt;cweagans/composer-patches&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;composer require cweagans/composer-patches&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Хакаем, собственно, модуль.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Переходим в директорию с модулем и делаем патч:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git diff HEAD &amp;gt; contrib_module_patch_1.patch&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Если в директории модуля отсутсвует &lt;code&gt;.git&lt;/code&gt; и патч поэтому сделать не получается — удаляем модуль и ставим заново:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;composer require drupal/contrib_module --prefer-source&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Теперь патч должен получиться.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Переносим патч в какую-нибудь отдельную директорию, например &lt;code&gt;/patches&lt;/code&gt; в корне проекта.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Сбрасываем изменения в директории модуля:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git checkout .&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;В &lt;code&gt;composer.json&lt;/code&gt; в секцию &lt;code&gt;extra&lt;/code&gt; добавляем:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-composer&quot;&gt;&quot;patches&quot;: {
    &quot;drupal/contrib_module&quot;: {
        &quot;patches/contrib_module_patch_1.patch&quot;: &quot;patches/contrib_module_patch_1.patch&quot;
        // тут будут другие патчи этого модуля
    }
    // а тут патчи других модулей
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Теперь при запуске &lt;code&gt;composer install&lt;/code&gt; патч будет применяться автоматически. И если код модуля обновится так, что патч станет неприменим (например, его включат в код модуля) — композер ругнется и мы сможем проверить, в чем дело.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Дополнительная плюшка: в &lt;code&gt;patches&lt;/code&gt; можно добавлять не только рукотворные патчи, но и прямые ссылки на патчи, например, с &lt;a href=&quot;https://drupal.org&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;D.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;P.S. Ну и кинуть патч в ишью самого модуля не забудьте, для общего блага.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Fri, 11 Sep 2020 11:35:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2046 at https://graker.ru</guid>
    </item>
<item>
  <title>Формула плюрализации в Drupal 8</title>
  <link>https://graker.ru/news/2020/07/24/plural-formula-drupal-8</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Недавно заметил, что в одном из проектов после экспорта-импорта переводов (через po-файлы) поломалась плюрализация. То есть вместо обычных 3-х форм перевода на русский, стали появляться английские две формы. Раньше, несколько лет назад, с таким уже сталкивался. Чтобы починить, нужно было экспортнуть файл с сайта, где работает нормальная русская формула и импортнуть на сломанный.&lt;/p&gt;
&lt;p&gt;Но оказалось, что в Drupal 8 эта проблема начинается уже с экспорта. Экспортированный &lt;code&gt;ru.po&lt;/code&gt; с сайта, где с плюрализацией всё в порядке, внезапно содержал дефолтную английскую формулу. Попытка выкачать и вставить нормальную формулу со старого сайта на Drupal 7 тоже не помогла. При импорте просто ничего не происходило, формула оставалась дефолтной.&lt;/p&gt;
&lt;p&gt;Пришлось поковыряться в коде и оказалось что в Drupal 8 формула плюрализации хранится (в state) не в виде строки, а в виде массива вариантов. Пришлось сделать сначала &lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;drush eval &amp;quot;print_r(\Drupal::state()-&amp;gt;get(&amp;#039;locale.translation.formulae&amp;#039;, []));&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;на нормальном сайте для получения русской формулы.&lt;/p&gt;
&lt;p&gt;После чего оформить её в правильный массив и выполнить вот такой код:&lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;$formula = Array(
  &amp;#039;ru&amp;#039; =&amp;gt; Array(
    &amp;#039;plurals&amp;#039; =&amp;gt; 3,
    &amp;#039;formula&amp;#039; =&amp;gt; Array(
      1 =&amp;gt; 0,
      2 =&amp;gt; 1,
      3 =&amp;gt; 1,
      4 =&amp;gt; 1,
      21 =&amp;gt; 0,
      22 =&amp;gt; 1,
      23 =&amp;gt; 1,
      24 =&amp;gt; 1,
      31 =&amp;gt; 0,
      32 =&amp;gt; 1,
      33 =&amp;gt; 1,
      34 =&amp;gt; 1,
      41 =&amp;gt; 0,
      42 =&amp;gt; 1,
      43 =&amp;gt; 1,
      44 =&amp;gt; 1,
      51 =&amp;gt; 0,
      52 =&amp;gt; 1,
      53 =&amp;gt; 1,
      54 =&amp;gt; 1,
      61 =&amp;gt; 0,
      62 =&amp;gt; 1,
      63 =&amp;gt; 1,
      64 =&amp;gt; 1,
      71 =&amp;gt; 0,
      72 =&amp;gt; 1,
      73 =&amp;gt; 1,
      74 =&amp;gt; 1,
      81 =&amp;gt; 0,
      82 =&amp;gt; 1,
      83 =&amp;gt; 1,
      84 =&amp;gt; 1,
      91 =&amp;gt; 0,
      92 =&amp;gt; 1,
      93 =&amp;gt; 1,
      94 =&amp;gt; 1,
      101 =&amp;gt; 0,
      102 =&amp;gt; 1,
      103 =&amp;gt; 1,
      104 =&amp;gt; 1,
      121 =&amp;gt; 0,
      122 =&amp;gt; 1,
      123 =&amp;gt; 1,
      124 =&amp;gt; 1,
      131 =&amp;gt; 0,
      132 =&amp;gt; 1,
      133 =&amp;gt; 1,
      134 =&amp;gt; 1,
      141 =&amp;gt; 0,
      142 =&amp;gt; 1,
      143 =&amp;gt; 1,
      144 =&amp;gt; 1,
      151 =&amp;gt; 0,
      152 =&amp;gt; 1,
      153 =&amp;gt; 1,
      154 =&amp;gt; 1,
      161 =&amp;gt; 0,
      162 =&amp;gt; 1,
      163 =&amp;gt; 1,
      164 =&amp;gt; 1,
      171 =&amp;gt; 0,
      172 =&amp;gt; 1,
      173 =&amp;gt; 1,
      174 =&amp;gt; 1,
      181 =&amp;gt; 0,
      182 =&amp;gt; 1,
      183 =&amp;gt; 1,
      184 =&amp;gt; 1,
      191 =&amp;gt; 0,
      192 =&amp;gt; 1,
      193 =&amp;gt; 1,
      194 =&amp;gt; 1,
      &amp;#039;default&amp;#039; =&amp;gt; 2,
    )
  )
);

\Drupal::state()-&amp;gt;set(&amp;#039;locale.translation.formulae&amp;#039;, $formula);&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Тогда нормальная формула вернулась на место.&lt;/p&gt;
&lt;p&gt;На эту тему есть несколько ишью, залинкованных между собой, и пока не закрытых. Вот &lt;a href=&quot;https://www.drupal.org/project/drupal/issues/2882667&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;например&lt;/a&gt;. А пока — экспортируем и импортируем переводы осторожно.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Fri, 24 Jul 2020 09:40:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2043 at https://graker.ru</guid>
    </item>
<item>
  <title>Делайте дампы правильно</title>
  <link>https://graker.ru/news/2020/07/13/delajte-dumpy-pravilno</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Прислали тут мне дамп друпальной БД в таком формате. Сначала описание таблицы без ключей, затем вставка данных в таблицу, затем, в конце файла после всех таблиц и данных — объявление ключей для каждой таблицы. Хрен его знает, чем и зачем этот дамп так сделали. Но оказывается — в таком формате его нельзя импортироать в MySQL, настроенную на работу в кластере. На этапе вставки данных будет ругаться, что primary-ключей еще нет. Вот так:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ERROR 3098 (HY000) at line 40: The table does not comply with the requirements by an external plugin.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;А чтобы вылечить, надо накатить этот дамп куда-нибудь локально, без кластера. И затем сделать дамп уже обычным mysqldump. Там ключи сразу объявляются, в описании структуры таблиц.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Mon, 13 Jul 2020 10:32:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2042 at https://graker.ru</guid>
    </item>
<item>
  <title>Бобёр</title>
  <link>https://graker.ru/news/2019/09/25/bober</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Всегда скептически относился к объявлениям с заказами на Drupal.ru. Не потому что я такой зазнайка, а просто очень долго не удавалось нормальный заказ там подписать. Но все равно, на всякий случай просматривал объявления, иногда отвечал, и в конце-концов все-таки нашел.&lt;/p&gt;
&lt;p&gt;В прошлом году именно по объявлению на Д.ру удалось подписать контракт аж с «Первым каналом», и это было круто! Сейчас контракт формально и фактически завершился, так что можно и рассказать. Добавить результат в наше портфолио уже несколько месяцев руки не доходят, так что упомяну хотя бы здесь.&lt;/p&gt;
&lt;p&gt;Участвовали мы в разработке сайта &lt;a href=&quot;https://bober.ru/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;bober.ru&lt;/a&gt; — это сайт телеканала «Бобёр», который принадлежит организации «Первый канал. Всемирная сеть». Тематика канала — разнообразные рецепты и советы на тему DIY (то есть, Сделай сам). Как сажать смородину, снять-повесить радиатор, или собрать портативный ядерный реактор из часов, трусов и противогаза. Помимо «централизованного» контента, делиться всяким на сайте могут и пользователи.&lt;/p&gt;
&lt;p&gt;Дизайн и верстку сайта (html, стили, js) сделали на стороне заказчика. А мы делали бэк-энд на Drupal 8 и натягивали предоставленный фронт на тему Друпала. Делали авторизацию через социальные сети, поиск на Solr, пуш-уведомления, почтовые рассылки, QnA, комменты, блоги, модерацию и всякие вещи помельче.&lt;/p&gt;
&lt;p&gt;Это не самая долгая наша работа, но определенно одна из самых сложных и я ей горжусь. Были конечно бюрократические затруднения в процессе — но с крупными заказчиками так бывает почти всегда. На то мы и есть малый бизнес, чтобы проявлять гибкость и преодолевать такие трудности.&lt;/p&gt;
&lt;p&gt;Спасибо всем, кто участвовал! &lt;/p&gt;
&lt;p&gt;Отдельное спасибо руководителю проекта на стороне заказчика — за внимание, понимание, поддержку и высокий профессионализм. Было круто!&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Wed, 25 Sep 2019 07:50:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2031 at https://graker.ru</guid>
    </item>
<item>
  <title>Drupal 7 AWS S3 и проверка файла на существование</title>
  <link>https://graker.ru/news/2019/03/21/drupal-7-aws-s3-file-exists</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Есть в Drupal такой модуль, &lt;a href=&quot;https://www.drupal.org/project/s3fs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;S3FS&lt;/a&gt;, создает стрим-враппер &lt;code&gt;s3://&lt;/code&gt; для работы с файловыми бакетами на Amazon S3. Модуль в принципе удобный и работает, но вот только не все файловые функции умеют в такой стрим. Например, если мы хотим проверить, существует ли в бакете файл, то &lt;code&gt;file_exists(&#039;s3://myfile.txt&#039;)&lt;/code&gt; всегда вернёт &lt;code&gt;FALSE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Если заглянуть в код класса &lt;code&gt;S3fsStreamWrapper&lt;/code&gt;, то там для проверки используется &lt;code&gt;$this-&amp;gt;s3-&amp;gt;doesObjectExist()&lt;/code&gt;. Можно было бы сделать красиво, вот так:&lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;file_stream_wrapper_get_instance_by_scheme(&amp;#039;s3&amp;#039;)
  -&amp;gt;s3
  -&amp;gt;doesObjectExists(&amp;#039;my-bucket&amp;#039;, &amp;#039;myfile.txt&amp;#039;);&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Только вот незадача: &lt;code&gt;$this-&amp;gt;s3&lt;/code&gt; — клиент S3 &lt;code&gt;Aws\S3\S3Client&lt;/code&gt;, вокруг которого работает стрим-враппер — это protected-свойство.&lt;/p&gt;
&lt;p&gt;Пришлось ковыряться и делать некрасиво:&lt;/p&gt;&lt;/div&gt;
&lt;pre data-component-id=&quot;grakerru:code-block&quot; class=&quot;code-block language-none&quot;&gt;&lt;code class=&quot;language-none&quot;&gt;$config = _s3fs_get_config();
$s3 = _s3fs_get_amazons3_client($config);
$s3-&amp;gt;doesObjectExist(&amp;#039;my-s3-bucket&amp;#039;, $filename);&lt;/code&gt;&lt;/pre&gt;
&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;То есть вытягивать конфиги, создавать клиент вручную, и тогда уже проверять.&lt;/p&gt;
&lt;p&gt;А мораль такая. Если вы пишете враппер вокруг какого-нибудь сервиса, и решили сделать свойство, содержащее объект сервиса, недоступным снаружи — подумайте. Может хоть геттер добавить стоит, если уж не реализуете обертку над каждым полезным методом?&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Thu, 21 Mar 2019 07:15:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2010 at https://graker.ru</guid>
    </item>
<item>
  <title>Drupal и фильтр по редакциям</title>
  <link>https://graker.ru/news/2019/02/19/drupal-revisions-filtering</link>
  <description>&lt;p&gt;Как я уже упоминал, в коробке Drupal 8 есть такой полезный модуль Content Moderation. Он позволяет модерировать материалы на базе редакций (revisions): материал может быть в состоянии (moderation_state) &lt;em&gt;черновик&lt;/em&gt;, &lt;em&gt;опубликован&lt;/em&gt;, или &lt;em&gt;в архиве&lt;/em&gt;. Названия состояний можно менять, можно добавлять и новые состояния, и переходы между ними. При каждой смене состояния материала создается новая редакция. Благодаря этому можно, например, оставить проверенную редакцию опубликованной для всех пользователей сайта и, в то же время, работать с более новой редакцией в состоянии черновика.&lt;/p&gt;
&lt;p&gt;Если мы на сайте используем такую модерацию, рано или поздно нам может понадобиться программно загрузить все материалы, у которых последняя редакция в состоянии черновика. Например, чтобы их сосчитать, или еще зачем-то.&lt;/p&gt;</description>
  <pubDate>Tue, 19 Feb 2019 07:45:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2007 at https://graker.ru</guid>
    </item>
<item>
  <title>Drupal 8 и дефолтные редакции</title>
  <link>https://graker.ru/news/2019/02/15/drupal-8-default-revisions</link>
  <description>&lt;div class=&quot;paragraph paragraph--text&quot;&gt;&lt;p&gt;Есть в Друпале такая полезная штука — редакции (которые revisions). На базе редакций работает, например, модуль Content Moderation, реализующий workflow для модерации контента с помощью состояний (черновик — опубликовано — в архив, и всё такое). Благодаря управлению состояниями через редакции, можно без труда реализовать такой сценарий: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Пользователь добавляет статью как черновик.&lt;/li&gt;
&lt;li&gt;Модератор проверяет черновик и публикует статью.&lt;/li&gt;
&lt;li&gt;Пользователь вносит правки.&lt;/li&gt;
&lt;li&gt;Обновленная статья отправляется в черновики.&lt;/li&gt;
&lt;li&gt;Но отмодерированная ранее статья остается опубликованной, пока модератор не примет новую версию.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Возможность оставить опубликованную версию видимой достигается за счет того, что редакция материала в состоянии «опубликовано» объявляется дефолтной (revision_default). Именно её будет по умолчанию загружать Друпал для отображения, в то время как при редактировании будет загружаться последняя редакция материала.&lt;/p&gt;
&lt;p&gt;Так вот, нам может понадобиться проверить, является ли загруженная редакция сущности дефолтной. Для этого у контентных сущностей есть метод &lt;code&gt;isDefaultRevision()&lt;/code&gt;. Вот только работает он иногда несколько неожиданно и может этим выклевать весь мозг. Оказывается, если вызвать этот метод, например, из &lt;code&gt;hook_form_alter()&lt;/code&gt; при редактировании существующего материала (node/$id/edit) — он внезапно будет возвращать &lt;code&gt;FALSE&lt;/code&gt; всегда. Независимо от того, дефолтную редакцию мы правим, или нет. Видимо, для редактирования Друпал заранее создает новую не-дефолтную редакцию и сущность готовит уже в этой редакции. Или типа того.&lt;/p&gt;
&lt;p&gt;Так или иначе, поведение это совершенно контринтуитивное. Особенно учитывая, что если в этот момент запросить у сущности revision id — то вернётся как раз id дефолтной редакции (если редактируется она). Но &lt;code&gt;isDefaultRevision()&lt;/code&gt; все равно будет &lt;code&gt;FALSE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Возможность выкрутиться из этой странной ситуации, тем не менее, есть — в виде метода &lt;code&gt;wasDefaultRevision()&lt;/code&gt;, который проверяет, была ли эта редакция дефолтной при последнем сохранении сущности. Из &lt;code&gt;hook_form_alter()&lt;/code&gt; этот метод отрабатывает ожидаемо — возвращая &lt;code&gt;TRUE&lt;/code&gt;, если редактируется дефолтная редакция, и &lt;code&gt;FALSE&lt;/code&gt; — если последняя не-дефолтная. Такие дела.&lt;/p&gt;&lt;/div&gt;
</description>
  <pubDate>Fri, 15 Feb 2019 08:10:00 +0000</pubDate>
    <dc:creator>graker</dc:creator>
    <guid isPermaLink="false">2006 at https://graker.ru</guid>
    </item>

  </channel>
</rss>
