bff3339803
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
127 lines
5.3 KiB
Markdown
127 lines
5.3 KiB
Markdown
# WP Multi City
|
||
|
||
Мультигородская подсистема для WordPress: один сайт обслуживает несколько городов
|
||
по схеме `/{city}/{path}/` с подстановкой контента, ссылок и шорткодов.
|
||
|
||
**Версия:** 1.0.0 — MVP завершён.
|
||
|
||
## Требования
|
||
|
||
- WordPress 6.0+
|
||
- PHP 8.0+
|
||
- Advanced Custom Fields Pro
|
||
|
||
## Установка
|
||
|
||
1. Скачать zip последнего релиза:
|
||
<https://git.netranking.ru/bryzgalov/wp-multi-city/releases>
|
||
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/<slug-страницы>/` → увидеть «Тюменский тариф».
|
||
Открыть `/<slug-страницы>/` без префикса → пусто (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
|
||
|
||
### Automated (PHPUnit)
|
||
|
||
```bash
|
||
composer install
|
||
vendor/bin/phpunit
|
||
```
|
||
|
||
Expected: 104 tests, ~185 assertions green. Unit-level coverage via Brain Monkey
|
||
+ Mockery + Patchwork — no real WordPress required; полный suite за <1 секунду.
|
||
|
||
### Manual QA
|
||
|
||
Для end-to-end проверки против реального WordPress см. `docs/QA-CHECKLIST.md` —
|
||
13 секций (активация, admin UI, helpers, shortcode, router, page clones,
|
||
URL filters, REST URL).
|
||
|
||
## CI
|
||
|
||
`.gitea/workflows/test.yml` запускает PHPUnit на каждый push в `main` и каждый PR.
|
||
Активируется автоматически после push в Gitea.
|
||
|
||
## Roadmap MVP
|
||
|
||
| Этап | Содержание | Beads | Статус |
|
||
|---|---|---|---|
|
||
| S1 | Скелет (header, autoload, bootstrap) | cp-8ci | done |
|
||
| S2 | Taxonomy `town` + CPT `shortcode-town` + ACF `list_shortcode` | cp-q7g | done |
|
||
| 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` — MVP CLOSED.
|
||
|
||
## Источник
|
||
|
||
Плагин — переработка кастомной мультигородской подсистемы темы `washanyanya`
|
||
(1555 строк `inc/town-functions.php`) в переиспользуемый плагин для других проектов.
|
||
|
||
## Лицензия
|
||
|
||
GPLv2 или новее.
|