Open source

Написав для себе — віддаю всім

Написані для власних проєктів, потім доведені до загального вигляду. Кожен працює на живому сайті до публікації, а документація живе тут, а не в README.

GPLv3
форкайте і ставте клієнтам
Працює в продакшені
спершу на цьому сайті
5 репозиторії
понад 19 роки роботи

WP Bootstrapper

Чистка head, гарденінг і захист uploads.

WordPress друкує в head десяток рядків, які потрібні приблизно нікому: генератор із номером версії, RSD, wlwmanifest, shortlink, oEmbed-discovery, стилі емодзі. Gutenberg підключає свій CSS навіть там, де блоків немає. Усе це знімається фільтрами — питання в тому, що щоразу їх доводиться згадувати заново.

Це 48 перемикачів у семи вкладках, де кожен — один конкретний хук або константа ядра. Підписи так і написані: wp_generator, DISABLE_WP_CRON, should_load_separate_core_block_assets, big_image_size_threshold. Видно, що саме вимикається, і це можна перевірити за документацією WordPress.

  1. Шапка документа

    Генератор версії, RSD, wlwmanifest, shortlink разом з HTTP-заголовком, посилання на фіди, стилі віджета коментарів, скрипт і стилі емодзі, dns-prefetch на s.w.org.

  2. Гутенберг

    П'ятнадцять окремих перемикачів: wp-block-library та її тема, глобальні стилі, classic-theme-styles, патерни ядра, SVG-фільтри duotone в шапці, футері й адмінці, layout support, внутрішній контейнер групи.

  3. Захист uploads

    У wp-content/uploads пишеться керований блок .htaccess, що забороняє виконання php, php3–php8, phtml і phar, і паралельно збирається web.config для IIS — через DOMDocument, а не склеюванням рядків, тому чужі правила у файлі переживають запис. Запис атомарний; щоденний крон і самоперевірка повертають захист, якщо файл підмінили.

  4. Завантаження SVG

    SVG і SVGZ дозволені лише користувачеві з правом manage_options і перевіряються до потрапляння в uploads: спершу на script і foreignobject, обробники on* та javascript:, потім розбором через DOMDocument з вимкненою мережею. Окремий плагін для цього не потрібен.

  5. Перебір авторів

    Запити ?author=1 та author_name віддають гостям 404, а канонічний редирект глушиться, щоб WordPress не підказав правильну адресу сам.

  6. Вартість самого плагіна

    Усі налаштування лежать в одній опції та читаються один раз за запит. Залежностей немає взагалі: composer install не потрібен, репозиторій розгортається як є.

  7. Авторам плагінів

    Усередині — власний атрибут #[Hook]: методи позначаються ним прямо в класі, а завантажувач один раз збирає мапу хуків через Reflection і компілює її в статичний файл — далі Reflection не працює, а об'єкт класу створюється лише в момент спрацьовування хука. Поруч — fluent Settings API на DTO, яким описані всі сім вкладок. Якщо пишете свої плагіни, форкати варто саме це.

PHP 8.4+ · WordPress 6.7+ · GPLv3 — kostyasorokin/wp-bootstrapper на GitHub

Регіональний каталог WC

Ціни й каталог за містами, окремий URL на регіон.

Один магазин продає в кількох містах, і в кожному свої ціни, а іноді й свій асортимент. Звичний шлях — дублювати товари під кожне місто або підміняти ціну скриптом на одній адресі. Перше ламає облік, друге ламає кеш і пошукову видачу: у Києва і Львова один URL, і просувати нічого.

Натомість — ієрархічна таксономія region, справжні адреси вигляду /shop/kyiv/ і окрема пара цін — звичайна та акційна — на кожен регіон, що зберігається в мета-полях самого товару. Товар лишається один.

  1. Адреса на місто

    Кожному регіону — свій URL через власні правила перезапису. Це посадкова сторінка під регіональний запит, вона спокійно живе за повносторінковим кешем, і її можна просувати окремо.

  2. Ціни за регіонами

    Звичайна й акційна ціна задаються для кожного міста в картці товару. Дублів товару немає — отже, не роз'їжджаються залишки, артикули та звіти.

  3. Асортимент за регіонами

    Товар показується там, де він прив'язаний до регіону. Фільтрація йде через таксономію, а не важким запитом за мета-полями — на великих каталогах це різниця у швидкості, а не в стилі.

  4. Фід Google Merchant на кожен регіон

    Окремий XML-фід на регіон: кампанії ведуться за містами без ручного збирання фіда. Товар без ціни для запитаного регіону йде у фід зі звичайною ціною — це варто знати до того, як на фід спрямовано бюджет.

  5. Перемикач без JavaScript

    Вибір міста — звичайна форма, що надсилається на сервер. Жодного рядка фронтенд-скриптів: немає чому конфліктувати з темою і нічого чекати до промальовування.

PHP 8.3+ · WooCommerce · GPLv3 — kostyasorokin/wc-regional-catalog на GitHub

Telegram Integration

Події сайту — в Telegram, і вхід на сайт — із нього.

Пошта — поганий канал для сповіщення, на яке ніхто не відповідає. Вона повільна, падає у спам, а на сайті, чиєму серверу заборонено слати листи, не приходить зовсім. Telegram миттєвий, уже відкритий на телефоні й відповідає рівно на те питання, заради якого сповіщення існує.

Половина, яку ніхто не робить як слід, — зворотний шлях: вхід. Більшість плагінів вставляють копіпастний віджет логіна. Цей реалізує authorization code flow з PKCE і криптографічно перевіряє токен особи до того, як з'явиться сесія WordPress.

  1. Сесія, яку не вкрасти на льоту

    Потік пам'ятає, який браузер його почав. Callback-посилання, скопійоване з чужого адресного рядка, не можна програти заново й отримати чужий акаунт: state-кука своя на кожен потік, і розбіжність обриває спробу, а не впускає когось усередину.

  2. Дві прогалини, які лишає Telegram

    Він не повертає ні адреси пошти, ні надійного аватара. У нового акаунта пошта питається один раз, а фото профілю забирається лише по HTTPS і лише з хостів самого Telegram — імпорт картинки не можна перетворити на спосіб змусити сайт ходити за довільними адресами.

  3. Сповіщення — за типами, а не списком

    Контент, коментарі, користувачі, медіа, безпека, оновлення й Site Health — у кожного свій перемикач, а WooCommerce додає замовлення, залишки та події кошика. Перший рядок кожного повідомлення збирається з налаштовуваного власником заголовка, а не із зашитого шаблону.

  4. Він каже, коли зламаний

    Невдала доставка зберігає формулювання самого Telegram, чат призначення й розмір повідомлення — але ніколи не тіло: сповіщення може нести дані форми. Стан доставки віддається в Site Health, тож канал, що замовк, видно одразу, а не помічається з часом.

  5. Спам-фільтр під наглядом

    Безперервна серія заявок Contact Form 7, відхилених як спам, трактується як свідчення про сам фільтр, а не про відправників. Справжній спам приходить хвилями; фільтр, що відхиляє все підряд, — ні. Ця різниця була оплачена на цьому самому сайті.

  6. Авторам плагінів

    Інтеграції з іншими плагінами знаходяться скануванням каталогу й кешуються, а не живуть у списку, який хтось має не забути поправити. Хелпер кнопки входу повертає порожній рядок, коли плагін не завантажився, вхід вимкнено або відвідувач уже авторизований, — шаблон друкує його без жодної перевірки навколо.

GPLv3 — kostyasorokin/wp-telegram-integration на GitHub

Disable All Email

Один файл, що робить вихідну пошту неможливою.

Сайт, який не може доставляти пошту, не просто тихий. Боти заповнюють його форми, він надсилає підтвердження на будь-яку адресу, яку надав бот, і ці адреси належать реальним людям, які натискають "спам". За ними накопичуються відхилення, а адреса сервера потрапляє до списку заблокованих — зазвичай це помічають, коли хост пише, щоб запитати, що відбувається.

Зупинка поштового демона цього не запобігає. Бінарник sendmail на місці, PHP віддає листи прямо йому, а той сам відкриває з'єднання назовні. Демон вимкнений — пошта все одно йде.

  1. Два шари, з яких працює один

    Як must-use-плагін файл завантажується раніше, ніж WordPress оголосить власний wp_mail, — ім'я займається першим, і нижче за течією відправити не може ніхто. Якщо інший must-use-плагін встиг раніше, натомість відправник ядра зупиняється фільтром.

  2. Що відповідають викликачам

    Вирішує константа. Відповідь «успіх» дозволяє формам і оформленню замовлень завершуватися штатно; відповідь «помилка» — чесний варіант, коли іншого каналу доставки немає, ціною помилки на екрані в кожного відвідувача.

  3. Як потрапити назад

    Коли плагін падає фатально, WordPress шле посилання відновлення поштою, а в себе зберігає лише його хеш — робоче посилання не існує ніде, крім того листа. Воно перезбирається й записується туди, де його все ще можна прочитати, і передається в екшен, щоб його можна було надіслати іншим каналом.

  4. На що він не претендує

    Ніщо в PHP не перехопить код, який сам викликає функцію mail, відкриває власний SMTP-сокет або стукає в поштовий API голим cURL. Це закривається на сервері. Плагін закриває половину WordPress — і прямо каже, де живе друга.

GPLv3 — kostyasorokin/wp-disable-all-email на GitHub

KS Projects

Архів портфоліо, який переживає тему, у якій його зробили.

Портфоліо зазвичай живе в темі: там оголошено тип запису, теги й усі кейси. Це працює до заміни теми — а тоді разом із нею зникає і весь архів, чого портфоліо робити не має за жодних обставин.

Це той самий архів, але окремим типом вмісту, з межею, проведеною у визначеному місці: плагіну належать дані та екрани редагування, темі — те, як усе це виглядає.

  1. Заготовки, які тема перемагає ім’ям файлу

    Із плагіном їдуть три прості шаблони, щоб новий сайт виглядав портфоліо, а не стрічкою блогу. Тема перехоплює будь-який із них, просто маючи файл із тим самим іменем: нічого перемикати чи скасовувати не треба. Класів фреймворків у заготовках немає навмисно — заготовка зі своїм оформленням виглядала б недоречно в будь-якій темі, крім тієї, звідки вона походить.

  2. Що кейсу потрібно насправді

    Два метабокси. Картка тримає коротке ім’я, підзаголовок і адресу, за якою робота вийшла у світ, — заголовок у портфоліо зазвичай ціле речення, а сітці потрібне ім’я. Титри тримають те, що просив клієнт, хто працював і що зроблено, — полями, а не написаним руками HTML, тому редизайн не означає правку кожного проєкту вручну.

  3. Шаблон під кожен проєкт

    Одному кейсу потрібна галерея на всю ширину, іншому — довгий текст. Проєкт може назвати PHP-файл у темі, і той виводиться замість вмісту запису й тільки замість нього: заголовок, теги й титри лишаються за темою. Вимкнення шаблона одразу повертає версію з редактора, а зниклий файл відкочується до неї, а не залишає порожню сторінку.

  4. Налаштування, якого навмисно немає

    Слаги в адресах змінювати можна. Імена типу запису й таксономії — ні: це ті самі рядки, під якими лежить кожен запис у базі, і винести їх у налаштування означало б дати спосіб втратити архів одним кліком. Задати їх, як і раніше, можна у wp-config.php — до появи першого проєкту й ніколи після.

  5. Як він влаштований усередині

    Класи за PSR-4, і хук оголошено просто на методі, який його обробляє, а не в списку реєстрацій десь осторонь: за цим немає ні скомпільованого кешу, ні обходу тек, тому один файл каже, з чого плагін складається. API, до якого звертається тема, — один клас і один імпорт. Залежностей у рантаймі немає зовсім: репозиторій працює одразу після клонування.

  6. Що проганяється перед релізом

    Статичний аналіз на найсуворішому рівні PHPStan, перевірка стандартів коду із записаною причиною біля кожного відступу та модульні тести на те, про що можна міркувати окремо. Дві перевірки існують тому, що інакше їхня поломка мовчазна: одна не пропускає автозавантажувач у постачанні, що розійшовся з вихідниками, друга — переклад, який відредагували, але не скомпілювали.

PHP 8.5+ · WordPress 6.7+ · GPLv3 — kostyasorokin/wp-ks-projects на GitHub

Забирайте й користуйтеся

Усе це безкоштовно й відкрито — ставте на свої проєкти й на клієнтські. Помилки та пропозиції — в issues на GitHub. Доопрацювання під конкретний сайт або щось нове для системи, якої тут ще немає, — окрема робота, і про неї варто написати.