diff --git a/README.md b/README.md index 8d7832a..0c94a46 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # WP Multi City -Мультигородская подсистема для WordPress: один сайт обслуживает несколько городов по схеме `/{city}/{path}/` с подстановкой контента, ссылок и шорткодов. +Мультигородская подсистема для WordPress: один сайт обслуживает несколько городов +по схеме `/{city}/{path}/` с подстановкой контента, ссылок и шорткодов. -**Статус:** v0.1.0 — скелет. Функционал в разработке (см. roadmap ниже). +**Версия:** 1.0.0 — MVP завершён. ## Требования @@ -10,10 +11,73 @@ - PHP 8.0+ - Advanced Custom Fields Pro -## Установка (на v0.1.0) +## Установка -1. Скачать архив или склонировать в `wp-content/plugins/wp-multi-city/`. -2. Активировать в админке WP. Если ACF Pro не активен — увидите admin-notice об ошибке зависимости. +1. Скачать zip последнего релиза: + +2. WP admin → Plugins → Add new → Upload (или распаковать в `wp-content/plugins/wp-multi-city/`). +3. Активировать. Если ACF Pro не активен — увидите admin notice об ошибке зависимости. + +Обновления приходят автоматически: плагин-update-checker опрашивает Gitea hourly. +Force-check: WP admin → Plugins → «Check again». + +## Quick Start (5 минут) + +1. WP admin → **Шорткоды → Города** → создать term `tyumen`, `spb`. +2. WP admin → **WP Multi City** → выставить `main_town_slug` = `spb`. +3. WP admin → **Шорткоды → Добавить** пост: + - title: `Тарифы` + - ACF repeater `list_shortcode`: row town=tyumen, text="Тюменский тариф". + - Запомнить ID поста (например 42). +4. Создать страницу с контентом `[shortcode_dmr id=42]`. +5. Открыть `/tyumen//` → увидеть «Тюменский тариф». + Открыть `//` без префикса → пусто (main_town=spb, не tyumen). + +## Hook API + +### Процедурные функции + +| Функция | Возвращает | Назначение | +|---|---|---| +| `wpmc_current_town()` | `?string` | town slug из текущего URL или null | +| `wpmc_get_term_by_slug($slug)` | `?\WP_Term` | `town`-term по slug | +| `wpmc_alt_get_field($key, $post_id)` | `mixed` | `get_field` с fallback на term meta | +| `wpmc_remove_domain_link($url)` | `string` | strip `home_url` prefix | +| `wpmc_main_town_slug()` | `?string` | slug из options page | + +### WP-фильтры от плагина + +- `the_title` / `single_cat_title` → `do_shortcode` (priority 9999, после Yoast SEO). +- `home_url` / `post_link` / `acf/load_value` → `LinkFilter::add_town_prefix` (auto-prefix URL текущим town). +- `rest_url` → `RestUrlFilter::preserve_host` (форсирует HTTPS + `HTTP_HOST`). + +### Bypass URL-фильтров + +Когда нужно построить «канонический» URL без городского префикса: + +```php +$canonical = \WPMultiCity\Helpers::without_url_filters( + fn() => get_permalink($post_id) +); +``` + +Counter-based, поддерживает вложенные вызовы. + +## Migration guide (из темы washanyanya) + +1. В `wp-content/themes/washanyanya/functions.php` закомментировать + `require_once get_template_directory() . '/inc/town-functions.php';`. +2. Активировать wp-multi-city. +3. ACF Pro field group из темы → re-import в новую location (CPT `shortcode-town`). +4. Заменить вызовы `current_town()` на `wpmc_current_town()`. Либо прописать + алиас в functions.php темы: + ```php + if (function_exists('wpmc_current_town')) { + function current_town(): ?string { return wpmc_current_town(); } + } + ``` +5. Проверить: `/tyumen/about/` отдаёт правильный page; меню префиксится; + `[shortcode_dmr]` рендерит. ## Testing @@ -24,15 +88,19 @@ composer install vendor/bin/phpunit ``` -Expected: 98 tests, 175 assertions green. Unit-level coverage via Brain Monkey + Mockery + Patchwork — no real WordPress required; the full suite runs in under one second. +Expected: 104 tests, ~185 assertions green. Unit-level coverage via Brain Monkey ++ Mockery + Patchwork — no real WordPress required; полный suite за <1 секунду. ### Manual QA -For end-to-end verification against a real WordPress installation, see `docs/QA-CHECKLIST.md` — 13 sections covering activation, admin UI, helpers, shortcode, router, page clones, URL filters, REST URL. +Для end-to-end проверки против реального WordPress см. `docs/QA-CHECKLIST.md` — +13 секций (активация, admin UI, helpers, shortcode, router, page clones, +URL filters, REST URL). -### CI +## CI -`.gitea/workflows/test.yml` runs PHPUnit on every push to `main` and every pull request. The workflow becomes active once the repo is mirrored to Gitea (S7). +`.gitea/workflows/test.yml` запускает PHPUnit на каждый push в `main` и каждый PR. +Активируется автоматически после push в Gitea. ## Roadmap MVP @@ -40,14 +108,19 @@ For end-to-end verification against a real WordPress installation, see `docs/QA- |---|---|---|---| | S1 | Скелет (header, autoload, bootstrap) | cp-8ci | done | | S2 | Taxonomy `town` + CPT `shortcode-town` + ACF `list_shortcode` | cp-q7g | done | -| S3 | `[shortcode_dmr id=N]` + хелперы (`current_town`, `_alt_get_field`, `remove_domain_link`) | cp-arq | done | -| S4 | URL-роутер `/{city}/{path}/` + `page_unic` + `main_page_alt` | cp-83m | done | -| S5 | Фильтры `the_title`/`the_content`/`the_permalink`/`rest_url` | cp-i17 | done | -| S6 | PHPUnit-тесты | cp-la7 | done | -| S7 | Релиз через Gitea + plugin-update-checker | cp-7cf | open | +| S3 | `[shortcode_dmr id=N]` + хелперы | cp-arq | done | +| S4 | URL-роутер `/{city}/{path}/` | cp-83m | done | +| S5 | Глобальные фильтры (`the_title`/URL/`rest_url`) | cp-i17 | done | +| S6 | CI workflow + manual QA checklist | cp-la7 | done | +| S7 | Gitea release + plugin-update-checker | cp-7cf | done | -Эпик: `cp-cw4`. +Эпик: `cp-cw4` — MVP CLOSED. ## Источник -Плагин — переработка кастомной мультигородской подсистемы темы `washanyanya` (1555 строк `inc/town-functions.php`) в переиспользуемый плагин для других проектов. +Плагин — переработка кастомной мультигородской подсистемы темы `washanyanya` +(1555 строк `inc/town-functions.php`) в переиспользуемый плагин для других проектов. + +## Лицензия + +GPLv2 или новее.