Как создать собственную страницу регистрации в WordPress Multisite. Как создать собственную страницу регистрации в WordPress Multisite Выносим статику на отдельный сервер и подключаем CDN

Создаем собственную страницу регистрации для мультисайта взамен стандартной wp-signup.php .

В обычной установке WordPress страницу регистрации (авторизации, сброса пароля) выводит файл wp-login.php .

  • /wp-login.php - авторизация
  • /wp-login.php?action=register - регистрация
  • /wp-login.php?action=lostpassword - сброс пароля

Для мультисайта в wp-login.php есть отдельные условия. Так, при переходе по ссылке /wp-login.php?action=register на мультисайте, WordPress сделает редирект на страницу /wp-signup.php . Во многих темах страница выглядит не очень привлекательно, поэтому мы сделаем свою собственную.

Основной сайт сети

По умолчанию, WordPress открывает страницу регистрации (wp-signup.php) на основном домене (сайте) сети. Тем не менее, можно сделать отдельную страницу регистрации для каждого сайта сети, даже если у них разные темы. Мы будем рассматривать случай, когда на всех сайтах сети есть своя собственная страница регистрации, но используется одинаковая тема и сайты различаются лишь языком. Если используются разные темы, потребуется написать больше кода.

functions.php?

Нет. Имя этого файла, кажется, упоминается в любой статье про WordPress. В нашем случае, с учетом того, что функционал регистрации рассчитан на несколько сайтов, имеет смысл вынести его в MU-плагины, которые загружаются при открытии любого сайта.

Лирическое отступление

Стоит отметить, что MU-плагины загружаются раньше обычных плагинов и до полной загрузки ядра WordPress, поэтому вызов некоторых функций может привести к фатальным ошибкам в PHP. Подобная «ранняя» загрузка имеет и свои плюсы. Скажем внутри любой темы нельзя цепляться к некоторым экшенам, которые срабатывают еще до загрузки файла functions.php из темы. Примером этого могут служить экшены из плагина Jetpack вида jetpack_module_loaded_related-posts (related-posts - название модуля) с помощью которых возможно отслеживать активность модулей в Jetpack. К этому экшену невозможно «прицепиться» из файла темы, потому что экшен уже сработал до загрузки темы - плагины загружаются раньше тем. Взглянуть на общую картинку порядка загрузки WordPress можно на странице Action Reference в кодексе .

Порядок в файлах

MU-плагины могут содержать любое количество файлов и любую стуктуру, которая покажется вам логичной. Я придерживаюсь примерно такой иерархии:

|-mu-plugins |-|-load.php |-|-|-selena-network |-|-|-|-signup |-|-|-|-|-plugin.php |-|-|-|-|-... |-|-|-|-jetpack |-|-|-|-|-plugin.php

В файле load.php подключаются все необходимые «плагины» для нашей сети:

// Load Traslates for all addons load_muplugin_textdomain ("selena_network", "/selena-network/languages/"); // Network Signup require WPMU_PLUGIN_DIR . "/selena-network/signup/plugin.php"; // Another plugins // require WPMU_PLUGIN_DIR ...

Внутри папки selena-network хранятся папки плагинов, в каждой есть свой plugin.php , которые мы и подключаем в load.php . Это дает гибкость и возможность быстро отключать и включать некоторые вещи.

Адрес страницы регистрации

Чтобы указать адрес страницы регистрации, используется фильтр wp_signup_location . Его можно найти внутри файла wp-login.php и именно он отвечает за редирект на wp-signup.php .

Case "register" : if (is_multisite()) { wp_redirect(apply_filters("wp_signup_location", network_site_url("wp-signup.php"))); exit;

Добавим свою функцию в mu-plugins/selena-network/signup/plugin.php , которая будет отдавать адрес страницы регистрации на текущем сайте:

Function selena_network_signup_page ($url) { return home_url () . "/signup/"; } add_filter ("wp_signup_location", "selena_network_signup_page", 99);

selena_network - префикс, который я использую в именах всех функций внутри MU-плагинов на своем сайте для избежания коллизий, его следует заменить на свой собственный уникальный префикс. Приоритет добавления фильтра 99, потому что некоторые плагины, например bbPress и BuddyPress могут перезаписать этот адрес на свой собственный (MU-плагины загружаются раньше, чем обычные плагины, см. выше). Обратите внимание, что используется home_url() , вместо network_site_url() , чтобы оставить посетителя на том же домене. В качестве адреса можно использовать любой URL.

Создание страницы

Теперь создадим страницу с адресом site.com/signup/ через обычный интерфейс, а в папке дочерней темы шаблон для нашей новой страницы - page-signup.php . Вместо слова «signup» можно использовать уникальный ID.

Внутри нового шаблона необходимо выполнить вызов функции selena_network_signup_main() , которая будет выводить форму регистрации.

Стоит заметить, что весь процесс с шаблонами не обязателен и вместо этого можно создать свой шорткод, который будет также вызывать функцию selena_network_signup_main() .

wp-signup.php и wp-activate.php

Теперь займемся созданием функции, которая будет выводить форму регистрации. Для этого скопируем файлы wp-signup.php и wp-activate.php из корня WordPress в mu-plugings/selena-network/signup/ (и не забываем их подключить внутри mu-plugins/selena-network/signup/plugin.php). Дальнейшие манипуляции с файлами крайне сложно и долго описывать, поэтому прийдется сделать их самостоятельно. Я лишь опишу что именно надо сделать и опубликую исходные файлы своего проекта:

  1. В начале файла удалить все require , вызов функций и прочий код вне функций.
  2. Переименовать все функции, добавив к именам уникальные префиксы.
  3. Нижнюю часть кода wp-signup.php обернуть в функцию selena_network_signup_main и в ее самом начале написать global $active_signup; .
  4. Заменить верстку на свою собственную в нужных местах.

Внутри wp-activate.php необходимо сделать примерно тоже самое:

  1. Удалить весь код вне функций, обернуть верстку в отдельную функцию.
  2. Изменить верстку в местах, где это необходимо.

Файл wp-activate.php отвечает за страницу активации аккаунта. Как и со страницей регистрации для нее необходимо создать отдельный шаблон, внутри которого вызывать функцию из файла wp-activate.php .

Отправляем письма активации

Страница регистрации отправляет посетителю письмо со ссылкой на активацию аккаунта. По умолчанию этим занимается функция wpmu_signup_user_notification() из файла ms-functions.php . Ее функционал можно заимствовать для своей функции. Причина, по которой необходимо отказаться от использования этой функции - она отправляет ссылку активации аккаунта с wp-activate.php . «Выключить» же эту функцию можно с помощью фильтра wpmu_signup_user_notification отдавая по нему false (если этого не cделать, письмо активации будет отправляться дважды, окей, на самом деле два разных письма).

Function armyofselenagomez_wpmu_signup_user_notification($user, $user_email, $key, $meta = array()) { // ... // Код из функции wpmu_signup_user_notification() wp_mail($user_email, wp_specialchars_decode($subject), $message, $message_headers); return false; } add_filter("wpmu_signup_user_notification", "armyofselenagomez_wpmu_signup_user_notification", 10, 4);

В результате страница регистрации в теме Селена стала выглядеть намного чище и аккуратней.

Заключение

В интернете множество других не очень правильных способов того, как сделать тоже самое - редиректы Apache, AJAX-формы, которые не будут работать без Java Script и т. п. Все это мне не очень понравилось, поэтому я постарался сделать это максимально правильно на своем собственном сайте.

Замечу, что править файлы следует осторожно и стараться не сильно отходить от исходных, чтобы в дальнешйем, в случае если WordPress изменит файлы wp-signup.php и wp-activate.php , их проще было сравнивать между собой для поиска изменений.

Не забывайте смотреть в исходный код всех описанных выше функций, чтобы полностью разобраться с тем, что и как происходит внутри кода.

Бонус. Защита от спамеров

Даже самые маленькие сайты на WordPress часто подвергаются налету спам-регистраций. Можно писать бесконечные условия для фильтрации ботов, зачастую больше похожие на попытку создать искусственный интеллект 🙂 В случае мультисайта мне очень помог обычный редирект в Apache, с помощью которого при открытии /wp-signup.php и /wp-acitvate.php я попросил выдавать 404 (я не эксперт по настройке Apache, поэтому мои правила могут быть не очень правильными).

RewriteEngine On RewriteBase / RewriteRule ^wp-signup\.php - RewriteRule ^wp-activate\.php - # BEGIN WordPress # Правила от WordPress по умолчанию не трогаем:) # ... # END WordPress

P. S. Я стараюсь максимально детально описывать некоторые сторонние вещи, потому что когда начинал я, порой некому было подсказать и объяснить многие вещи. Также я считаю, что подобные небольшие наводки на другие материалы кого-нибудь подтолкнут к изучению чего-то нового и расширению своей области знаний. В записях RewriteRule используются регулярные выражения, они совсем не сложные, например, символ ^ означает начало строки.

Advertisements

Знатный параноик и за каким-то чертом решили поставить wordpress, то… Первое, что пришло в голову - это «надо ограничить сему творению свободу!».

Настройки учетной записи, как и настройки php5-fpm, я опущу, так как у каждого свои тараканы, а кто-то вообще на apache запускает. Но вот общие для Wordpress я опишу в этой части. Напишу о том, что сделал, что получилось и почему.

Папки
  • wp-admin
  • wp-content
  • wp-includes
Файлы php

Это типичный набор для Wordpress 4.0.

Что же нам нужно? Нам нужно ограничить доступ к php файлам и админке, вынести статику, закрыть xmlrpc.

Ограничиваем доступ в админку и к php файлам

В моем варианте wordpress я не сохраняю комментарии пользователей и не использую xmlrpc. Как безопасно дать доступ на комментарии, как и ряд других насущных вопросов по nginx и wordpress будет расмотрен во второй части этой статьи, которая, естественно, будет создана при наличии оных. Так как тут нет apache, то файл.htaccess бесполезен.
Следовательно, закрываем указанные выше свистоперделки:

Location ~* ^/(\.htaccess|xmlrpc\.php)$ { return 404; }

После этого при запросах xmlrpc.php и.htaccess у нас будет 404 ошибка. Хотя можно выдать и 403 и 200 «trololo», но это уже дело вкуса.

Далее ограничиваем доступ к оставшимся. Под ограничением я имею в виду запрос авторизации, а именно auth_basic .

Location ~* ^/wp-admin/(.*(?

*данный код заставит nginx запрашивать авторизацию при запросе статики из /wp-admin/, статику выдает nginx.

Location ~* (/wp-admin/|/wp-cron\.php|/wp-config\.php|/wp-config-sample\.php|/wp-mail\.php|/wp-settings\.php|/wp-signup\.php|/wp-trackback\.php|/wp-activate\.php|/wp-links-opml\.php|/wp-load\.php|/wp-comments-post\.php|/wp-blog-header\.php|/wp-login\.php|/wp-includes/.*?\.php|/wp-content/.*?\.php) { auth_basic "protected by password"; auth_basic_user_file users/somefile; root /path/to/site/root; #еще параметры }

Запись вида /wp-includes/.*?\.php включает в себя все php файлы в wp-includes и ниже.

Готово, доступ мы закрыли. Теперь будем выборочно включать нужные нам элементы для паблик версии, а это дальше по тексту.

Включаем защищенные записи в нашем защищенном Wordpress

Так как мы закрыли wp-login.php авторизацией, то, написав защищенный пост и скинув ссылку и пароль (от поста) нужному пользователю, пользователь… испугается неведанного окна. Так как пароль передается файлу wp-login.php как post запрос с GET параметрами ?action=postpass .

nginx накладывает ряд ограничений:

  • в location от nginx мы не можем описать параметры запроса;
  • в if выражении нельзя использовать auth_basic;
  • игра с переменной в конфиге, которое передается 1 в случае удачной авторизации ничего не принесет, так как переменная живет только в текущем запросе .
Что же делать?

Решение есть! Создать символическую ссылку на wp-login.php в той же папке. У меня это wp-postpass.php . Символическая ссылка нужна для того, что если мы обновим wordpress, то wp-login.php тоже обновится и обновится файл по ссылке… Вот за что я люблю linux.

Следом в конфиге nginx прописываем:

Location ~* (/wp-postpass\.php) { if ($args ~ "^action=postpass$") { set $wppostpass 1; } if ($wppostpass ~ 0) { return 403; } #еще параметры }

В таком случае при запросе /wp-postpass.php?action=postpass переменная wppostpass примет значение 1, и location отработает до конца. В случае голого запроса wp-postpass.php или с другими параметрами (как видит тут проверяется от начала ^ до конца$ строки) будет ошибка 403, что означает доступ закрыт.

Для работы такой схемы нам нужен ngx_http_substitutions_filter_module . В конфиге следует прописать

Subs_filter "https://example.com/wp-login.php\?action=postpass" "https://example.com/wp-postpass.php?action=postpass" gi;

Выносим статику на отдельный сервер и подключаем CDN

В нагрузке js, css и мелкие gif"ки роли не играют, так как при наличии памяти nginx хранит их в своем кеше, а при наличии достаточного количества памяти всю статику сайта можно вынести на tmpfs раздел (3.8 Гб чтение-запись и 745к iops"ов к примеру).

Но в случае одного сервера кто-то получит файл раньше, кто-то позже, и если у нас много клиентов, то при раздаче 1000 файлов по 1Мб канал нехило просядет, если не вводить rate.

Вот для этих случаев и придуманы кеширующие CDN провайдеры. Для примера - cloudflare .

Принцип работа замечательно проиллюстрирован на их картинке:

Без CDN все запросы идут на конечный сайт, а с CDN запросы идут на CDN провайдера, который выступает как промежуточное звено. И в этом случае если 1000 пользователей запросят файл размеров 1 Мб, то этот файл будет запрошен CDN провайдером 1 раз для своего кеша, и затем раздан той 1000 пользователей. Варианты DDoS"а в стиле à la google docs, когда запросили big_photo.jpg ?ver=1 , затем big_photo.jpg ?ver=2 , и т.д. не сработает, если выбран режим умеренного кеширования (у cloudflare он есть) и кеширование только статики, то при запросе big_photo.jpg , big_photo.jpg?ver=1 или big_photo.jpg?ver=123 с сервера запрашивается big_photo.jpg и затем раздается он и только он, даже если клиент запрашивает файл с аргументами (они просто игнорируются). Это решает проблему ддоса cdn провайдером, который по сути должен и от ддоса защищать.

Я не сильно лазил, но нашел, что дефолтовая статика хранится в:

  • /wp-content/uploads/
  • /wp-content/themes/
  • /wp-content/plugins/
  • /wp-includes/js/
  • /wp-includes/css/
  • /wp-includes/certificates/
  • /wp-includes/fonts/
  • /wp-includes/images/
Соответственно для них мы и сделаем новые правила в location и будем использовать nginx c ngx_http_substitutions_filter_module .
Ставить этот модуль не обязательно, можно обойтись одними лишь rewrite"ами, но сам по себе он полезный и через него можно улучшить тот или иной вывод с backend"а.

В конфиг добавляем:

Subs_filter_types text/html; subs_filter_types text/xml;

Чтобы фильтровать вывод html и xml документов.

Subs_filter "https://example.com/wp-content/uploads/" "https://static.example.com/uploads/" gi; subs_filter "https://example.com/wp-content/themes/" "https://static.example.com/themes/" gi; subs_filter "https://example.com/wp-content/plugins/" "https://static.example.com/plugins/" gi; subs_filter "https://example.com/wp-includes/js/" "https://static.example.com/js/" gi; subs_filter "https://example.com/wp-includes/css/" "https://static.example.com/css/" gi; subs_filter "https://example.com/wp-includes/certificates/" "https://static.example.com/certificates/" gi; subs_filter "https://example.com/wp-includes/fonts/" "https://static.example.com/fonts/" gi; subs_filter "https://example.com/wp-includes/images/" "https://static.example.com/images/" gi;

Location ~* ^/wp-content/themes/(.*(?

В итоге, при запросе любого php файла ничего не будет. А при запросе статики (все что не php в случае с WP, что логично) пользователь будет перенаправлен на сервер статики.

Настройка профиля nginx для сервера статики будет рассмотрена .

Затем остается лишь сделать аккаунт на cloudflare (или любом) другой cdn провайдере, который вы собираетесь использовать, прописать их DNS у себя и включить кеширование домена static.example.com, без кеширование example.com, где работает wordpress.

Настройка сервера статики

Так как мы перенесли отдачу на сервер статики, то необходимо его правильно настроить.

Allow 127.0.0.1; allow IPv4 сервера; allow IPv6 сервера; allow IP/подсеть серверов CDN; ... allow IP/подсеть серверов CDN; deny all;

Требуется разрешить доступ локалхосту, доступ самому серверу с внешнего IP (например какой скрипт) и серверам CDN провайдера. Например, подсети CloudFlare можно найти вот по этой ссылке. И, конечно же, закрыть доступ всем остальным. Так как если CDN внезапно решит пустить траффик на прямую… оставить свободный канал.

Так же надо сделать dummy директорию как root для всего сервера статики.

Root /path/to/site/dummy;

Чтобы запросы, которые пришли на сервер статики на location / или =/ и которые не соответствуют прописанным там location пошли в ту самую dummy директорию. Эта директория прописывается внутри server{} .

Location =/ { default_type text/html; return 200 "c"est static, c"est simple:P"; }

Это текст, который увидит пользователь, запросивший корень. Писать можно что угодно, главное при использовании внутри " экранировать кавычки как \" .

Затем следует прописать location "ы на статику:

Location ~* ^/uploads/.*(?

При запросе static.example.com/images/pic.png сервер отдаст файл из директории /wp-includes/images/ файл pic.png , но при запросе static.example.com/images/pic.php location прощелкает и в итоге пользователю отдадут файл из dummy/images/pic.php, которого нет и как итог ошибка 404.

Еще надо добавить рейты на скорость.

Limit_rate_after 16m; limit_rate 2m;

После 16 мегабайт скорость уменьшается до 2 Мб в секунду на поток . Это чтобы CDN при кешировании огромного файла не забил весь канал.

В случае с cloudflare максимальный размер файла (на момент написания этого материала) составляет 512 мегабайт , а поддерживаемые форматы на бесплатном тарифном плане включают : css, js, jpg, jpeg, gif, ico, png, bmp, pict, csv, doc, pdf, pls, ppt, tif, tiff, eps, ejs, swf, midi, mid, ttf, eot, woff, otf, svg, svgz, webp, docx, xlsx, xls, pptx, ps, class, jar.

Фильтрация запросов

Тут сразу два случая:
  1. При загрузке медиафайлов они получают ссылку вида example.com/?attachment_id=XX , где XX это id странички для этого медиафайла. Соотвественно перебирая 1, 2, 3… пользователь может выкачать весь контент, причем и ту его часть, которая ему не предназначается;
  2. php так и пестрит болячками. Наверное, тут не столько архитектура языка, сколько скилы программистов и настройки среды, в которое сие творение вертится. Но раз поставили wordpress, то будем готовится к будущим багам.
Для этого пропишем в server {} нашего конфига для nginx код:

If ($args ~* "(attachment_id|eval|duplicate|base64|substring|preg_replace|create_function)") { return 403; }

Тогда если в аргументах запроса встретятся attachment_id, eval, duplicate, base64, substring, preg_replace, create_function nginx вернет ошибку 403, причем запрос не будет передан на динамику для исполнения потенциальной уязвимости.

Плюшки через subs_filter от nginx

Предназначение этого модуля было рассмотрено .

Задача: wordpress по умолчанию открывает ссылки на медиафайл в текущем окне. А нужно, чтобы в новом.

Решение:

Subs_filter "" "" gi; subs_filter "" "" gi;

Решение: добавить небольшой код в когфиг nginx.

Subs_filter "https://example.com/xmlrpc.php" "https://example.com/xmlrpc.txt" gi;

Ну а в xmlrpc.txt можно засунуть пасхалочку.

Послесловие

Удачи вам!

Теги: Добавить метки

Позволяет использовать одну установку WordPress для нескольких сайтов одновременно. При этом каждый сайт получает свои собственные таблицы в базе данных с уникальным префиксом.

Таблицы с данными зарегистрированных пользователей общие для всех сайтов сети. Это несомненный плюс и зарегистрировавшись однажды можно получить доступ к нескольким сайтам. Причем на каждом сайте один и тот же аккаунт может иметь разные права. Например, на одном сайте пользователь может быть редактором, а на другом администратором.

В обычной установке WordPress страницу регистрации, авторизации и сброса пароля выводит файл wp-login.php .

  • wp-login.php — авторизация
  • wp-login.php?action=register — регистрация
  • wp-login.php?action=lostpassword — сброс пароля

В режиме Multisite ядро WordPress начинает вести себя несколько иначе и при переходе по ссылке wp-login.php?action=register произойдет редирект на wp-signup.php . Это страница регистрации вашей сети, которая по умолчанию есть в WordPress.

Помимо регистрации обычных пользовательских аккаунтов на ней можно создать и новый сайт, если суперадминистратор включил такую возможность в настройках сети (Network Admin → Settings → Network Settings).

В большинстве тем страница регистрации выглядит не совсем хорошо. Многие темы оформления используют CSS-фреймворки, например, Bootstrap, и собственные специфичные классы для стилизации разных элементов на страницах, поэтому тяжело написать единый HTML, который подойдет всем.

Но не стоит отчаиваться, если страница выглядит неопрятно. Файл wp-signup.php отличная вещь на первых порах, когда нет времени прорабатывать каждую деталь сайта — можно сосредоточиться на других более важных страницах и контенте.

Когда вы будете готовы сделать свою собственную страницу регистрации, wp-signup.php будет хорошим образцом и примером, по которому легко разобраться в спектре функций, которые предоставляет WordPress для обработки и проверки введенных пользователями данных и создания новых аккаунтов.

Основной сайт сети

По умолчанию, WordPress открывает страницу регистрации (wp-signup.php) на основном домене (сайте) сети. Тем не менее, можно создавать страницы регистрации для каждого сайта сети, даже если у них и темы.

Мы будем рассматривать случай, когда на всех сайтах сети используется одна тема, но на каждом из них есть страница регистрации. Сайты различаются языком (английский и русский), поэтому страница регистрации будет выводиться на «родном» языке сайта. В случае, если сайты используют разные темы, все будет зависеть от того, какие именно это темы, подойдет ли им одинаковая верстка (отличная ситуация, которая может подтолкнуть вас к унификации всех своих тем) или стоит прорабатывать страницы индивидуально.

Альтернатива functions.php

Порядок в файлах

MU-плагины могут содержать любое количество файлов и структуру, которая покажется вам логичной. Я придерживаюсь примерно такой иерархии:

| mu-plugins | | load.php | | selena-network | | | signup | | | | plugin.php | | | ... | | | jetpack | | | | plugin.php

В файле load.php подключаются переводы и все необходимые «плагины»:

// Загрузка переводов для MU-плагинов load_muplugin_textdomain("selena_network", "/selena-network/languages/"); // Функционал для страницы регистрации require WPMU_PLUGIN_DIR . "/selena-network/signup/plugin.php"; // Еще один плагин // require WPMU_PLUGIN_DIR ...

Внутри директории selena-network хранятся папки плагинов. В каждой есть свой plugin.php , которые мы и подключаем в load.php . Это дает гибкость и возможность мгновенно отключать и включать отдельные компоненты на рабочем проекте в случае экстренной необходимости.

Страница регистрации

Разобравшись с тем, где и как мы будем писать код, можно переходить к созданию страницы регистрации.

Создадим страницу с адресом example.org/signup/ через обычный интерфейс. В качестве адреса можно использовать любой URL, который покажется подходящим для вашего проекта.

Редирект на нужную страницу регистрации

Чтобы WordPress узнал о нашей новой странице регистрации и производил редирект именно на нее, при клике на ссылку «Зарегистрироваться», используется фильтр wp_signup_location . Его можно найти внутри wp-login.php и именно он отвечает за редирект на wp-signup.php по умолчанию.

Case "register" : if (is_multisite()) { wp_redirect(apply_filters("wp_signup_location", network_site_url("wp-signup.php"))); exit; // ...

Как вы помните, по умолчанию, страница регистрации открывается на основном домене сети. Именно поэтому здесь используется network_site_url() .

Добавим свой обработчик к фильтру в mu-plugins/selena-network/signup/plugin.php , который будет отдавать адрес страницы регистрации на текущем сайте:

Function selena_network_signup_page($url) { return home_url("signup"); } add_filter ("wp_signup_location", "selena_network_signup_page", 99);

selena_network — префикс, который я использую в именах всех функций внутри MU-плагинов на своем сайте для избежания коллизий, его следует заменить на свой собственный уникальный префикс. Приоритет добавления фильтра 99, потому что некоторые плагины, например, bbPress и BuddyPress могут перезаписать этот адрес на свой собственный (MU-плагины загружаются раньше, чем обычные плагины, см. выше).

Обратите внимание, что используется home_url() , которая в отличие от network_site_url() , отдает адрес текущего сайта, а не главного сайта сети.

Функционал wp-signup.php

Файл wp-signup.php содержит большое количество функций и кода. Чтобы увидеть картину в целом можно воспользоваться сворачиванием кода. Как правило, по-английски это называется «code folding».

В самом начале файла с 1 по 80 строчку (в версии 4.1.1) производятся различные проверки и вывод «старта» страницы с помощью get_header() .

Далее объявляются множество методов и перед тем, как мы начнем работать с ними, стоит разобраться что делает каждая функция. Внутри многих из них часто используются другие функции с префиксом wpmu_ , все они объявляются в файле wp-includes/ms-functions.php . Этот раздел тяжело понять не видя код самостоятельно. Ниже небольшое описание основных функций на случай, если у вас возникнут затруднения.

  • wpmu_signup_stylesheet() — вывод дополнительного CSS на странице регистрации.
  • show_blog_form() — поля для регистрации сайта (адрес, название видимость для поисковых систем).
  • validate_blog_form() — проверка введенного адреса сайта и названия с помощью wpmu_validate_blog_signup() .
  • show_user_form() — поля для регистрации пользователя (логин и адрес эл. почты).
  • validate_user_form() — проверка введенного логина и адреса эл. почты с помощью wpmu_validate_user_signup() .
  • signup_another_blog() — поля для регистрации новых сайтов с помощью show_blog_form() для пользователей, которые уже зарегистрированы на сайте.
  • validate_another_blog_signup() — проверяет адрес сайта и название с помощью validate_blog_form() .
  • signup_user() — основная функция для вывода полей страницы регистрации.
  • validate_user_signup() — проверяет логин и адрес эл. почты с помощью validate_user_form() .
  • signup_blog() — поля для ввода адреса, названия и видимости сайта (второй шаг регистрации) с помощью show_blog_form() .
  • validate_blog_signup() — проверяет логин, адрес эл. почты, адрес и название сайта.

В самом низу файла wp-signup.php (со строчки 646 в версии 4.1.1) основная логика работы страницы регистрации, которая использует все выше описанные методы. Эта часть кода не вынесена в функцию. В конце вызывается get_footer() .

Копируем функционал wp-signup.php

Далее будет описана процедура копирования wp-signup.php в MU-плагины и внесению изменений в «форк». Возможно, это может показаться не самым правильным путем. Вместо этого можно с нуля написать свои функции для проверки и вывода форм используя классы, а не обычные функции. На мой взгляд в wp-signup.php уже есть вся необходимая логика для нашей страницы, остается лишь внести небольшие изменения.

При обновлении WordPress время от времени меняется и wp-signup.php , но это не значит что при каждом релизе придется синхронизировать свой «форк». Функции внутри wp-signup.php по сути занимаются лишь выводом HTML, проверкой данных, созданием учетных записей и сайтов занимаются методы с префиксом wpmu_ , объявленные в ms-functions.php .

Займемся созданием функции, которая будет выводить форму регистрации на странице. Для этого скопируем wp-signup.php из корня WordPress в mu-plugings/selena-network/signup/ . Подключим его внутри mu-plugins/selena-network/signup/plugin.php).

Require WPMU_PLUGIN_DIR . "/selena-network/signup/wp-signup.php";

Удалим из самого начала скопированного файла все require и ненужные проверки. В версии 4.1.1 это весь код с 1 по 80 строчку.

Теперь мы готовы создать главную функцию для вывода формы регистрации. Для этого всю логику со строчки 646 и до самого конца файла перенесем в функцию c названием selena_network_signup_main . В самом конце удалим два лишних закрывающих

(строчки 722 и 723), а также вызов get_footer() .

В только что созданной selena_network_signup_main() в самом начале объявим глобальную переменную active_signup , которую используют все остальные методы из этого файла. И добавим вызов события before_signup_form , которое мы удалили из самого начала файла.

Function selena_network_signup_main() { global $active_signup; do_action("before_signup_form"); // ... }

Теперь остается лишь изменить верстку во всех местах где это необходимо и страница регистрации готова.

Вывод формы регистрации

Здесь есть как минимум два варианта. Более удобный способ — создать шорткод и разместить его на странице через обычный редактор.

// Создаем шорткод network_signup add_shortcode("network_signup", "selena_network_signup_main");

Второй вариант — создать в папке дочерней темы шаблон страницы page-signup.php . Вместо слова «signup» можно использовать уникальный ID, присвоенный странице. Внутри шаблона добавить необходимую верстку и сделать вызов selena_network_signup_main() в нужном месте.

В результате моя страница регистрации стала выглядеть намного лучше и чище.

Страница активации

По умолчанию WordPress условно делит процесс регистрации в Multisite на два шага — заполнение формы на сайте и активация аккаунта при переходе по ссылке отправленной в электронном письме. После того, как вы заполните форму, созданную в предыдущем разделе, WordPress отправляет письмо с небольшой инструкцией и ссылкой для активации аккаунта.

За вывод страницы активации отвечает файл wp-activate.php расположенный в корневой директории WordPress. wp-activate.php можно так же полностью изменить. Процесс схож с тем, что мы уже делали для wp-signup.php .

Создадим страницу example.org/activate/ через обычный интерфейс. В качестве адреса используйте любой URL, который покажется вам подходящим.

Скопируем файл wp-activate.php к себе в MU-плагины и подключим его в mu-plugins/selena-network/signup/plugin.php .

Require WPMU_PLUGIN_DIR . "/selena-network/signup/wp-activate.php";

Внутри не так много содержимого, в отличие от wp-signup.php . Файл выполняет единственную операцию — активирует аккаунт, если получен верный ключ и выводит сообщение об ошибке или успешном выполнении операции.

Удалим все ненужные проверки и require — с 1 по 69 строчку в WordPress 4.1.1. В самом конце уберем вызов get_footer() . Оставшееся содержимое перенесем в функцию selena_network_activate_main() .

Интересно заметить, что здесь перед загрузкой WordPress (wp-load.php) объявлялась константа WP_INSTALLING . Ее наличие заставляет WordPress не загружать плагины.

Как и в случае со страницей регистрации остается лишь исправить верстку там, где это необходимо. Также можно изменить текст выводимых сообщений (в этом случае не забудьте добавить текстовый домен своих MU-плагинов во все функции-переводчики, по умолчанию он нигде не установлен).

Готовую функцию можно использовать на заранее созданной странице через шорткод или отдельный шаблон в дочерней теме.

Письма активации с правильными ссылками

Страница активации готова к работе, но WordPress не знает о ней и по прежнему будет отправлять письма активации со ссылкой на wp-activate.php . В отличие от wp-signup.php здесь нет фильтра, который бы позволил изменить адрес. Вместо этого нужно написать свою функцию, которая будет отправлять письма с правильными ссылками.

В момент заполнения и отправки формы на странице регистрации WordPress вызывает wpmu_signup_user () или wpmu_signup_blog () в зависимости от типа регистрации. Обе функции создают новую запись в таблице wp_signups заполняя ее необходимым содержимым, среди которого есть и ключ активации аккаунта.

После, в зависимости от функции, вызывается wpmu_signup_user _notification() или wpmu_signup_blog _notification() . Обе функции имеют схожий функционал — генерируют и отправляют письмо со ссылкой активации, но принимают разные аргументы. В обоих есть фильтры для «перехвата» события.

If (! apply_filters("wpmu_signup_user_notification", $user, $user_email, $key, $meta)) return false;

Для активации аккаунтов с созданием блога:

If (! apply_filters("wpmu_signup_blog_notification", $domain, $path, $title, $user, $user_email, $key, $meta)) { return false; }

Остается лишь написать свои обработчики, внутри которых отправлять письма через wp_mail() , а в самом конце обязательно отдавать false , чтобы WordPress не отправил письмо активации дважды — одно ваше, другое — письмо по умолчанию со ссылкой на wp-activate.php .

Function selena_network_wpmu_signup_user_notification($user, $user_email, $key, $meta = array()) { // Генерируем заголовок, текст и заголовки письма // ... // Отправляем письмо или добавляем Cron-задачу для отправки письма wp_mail($user_email, wp_specialchars_decode($subject), $message, $message_headers); // Отдаем false, чтобы WordPress не отправил письмо активации дважды return false; } add_filter("wpmu_signup_user_notification", "selena_network_wpmu_signup_user_notification", 10, 4);

Если вы отправляете письма через SMTP-сервер или количество регистраций очень велико, следует задуматься о том, чтобы не отправлять письма мгновенно. Вместо этого можно добавлять Cron-задачи с помощью WordPress Cron .

Закрываем доступ к wp-signup.php и wp-activate.php

Создав свои собственные страницы регистрации и активации, может потребоваться закрыть «оригиналы». Например, если на странице регистрации есть дополнительные поля, которые необходимо обязательно заполнить. Также многие WordPress сайты подвергаются спам-регистрациям.

Решить две проблемы одним действием можно попросив Apache отдавать 404 в случае попытки открытия этих страниц. Для этого нужно лишь прописать пару дополнительных RewriteRule в ваш файл-конфигурацию или.htaccess .

RewriteEngine On RewriteBase / # Знание регулярных выражений никогда не будет лишним:) RewriteRule ^wp-signup\.php - RewriteRule ^wp-activate\.php - # BEGIN WordPress # Правила от WordPress по умолчанию не трогаем:) # ... # END WordPress

Заключение

Для этой и многих других «проблем» связанных с WordPress в интернете есть множество решений. Например, для создания страниц регистрации и активации некоторые предлагают переписывать оригинальные wp-signup.php и wp-activate.php . Этого не стоит делать, потому что в случае обновления WordPress вы потеряете все изменения, внесенные в файлы, а также не сможете, проверить целостность ядра с помощью .

При разработке любого дополнения, темы или решения следует потратить немного времени на то, чтобы разобраться с тем, что происходит внутри WordPress. Для этого есть множество полезных дебаг-инструментов.

P.S.

Для автоматического назначения разных ролей новым пользователям можно использовать плагин Multisite User Management .

Если у вас возникли вопросы или трудности во время создания страниц регистрации и активации после прочтения статьи, оставьте комментарий и мы обязательно ответим.

27.03.2015 27.03.2015

WordPress разработчик. Любит порядок во всем и разбираться в новых инструментах. Вдохновлен архитектурой компонентов Symfony.

  • ln [-Ffhinsv] исходный_файл [ целевой_файл ] ln [-Ffhinsv] исходный_файл ... целевой_каталог link исходный_файл целевой_файл Программа ln создает запись в директории (ссылку) с именем, целевой_файл . На целевой_файл будут установлены те-же режимы, которые стоят на исходный_файл . Ссылки позволяют иметь несколько копий одного файла или каталога, размещенных в разных местах, но не занимая при этом дисковое пространство. Существует два типа ссылок, жесткие ссылки и символические ссылки. Каким образом ссылка указывает на исходный_файл , зависит от типа данной ссылки.

    Команда ln имеет следующие опции: -f Если целевой_файл уже существует, удалить его, чтобы можно было создать ссылку. Данная опция отменяет опцию -i . -F Если целевой_файл уже существует и является директорией, удалить его, чтобы можно было создать ссылку. Опция -F используется вместе с опциями -f или -i , в случае, если ни одна из них не указана, подразумевается опция -f . Эта опция не работает без опции -s . -h Если целевой_файл или целевой_каталог является символической ссылкой, не следовать по ей. Данная опция полезна в сочетании с опцией -f для замены символической ссылки, которая указывает на каталог. -i Интерактивный режим. Если целевой_файл существует, пользователю будет выведен запрос на удаление В случае согласия, ln удалит целевой_файл и создаст новую ссылку. Данная опция отменяет действие опции -f . -n Аналог опции -h , для совместимости с другими реализациями программы ln . -s Создавать символическую ссылку. -v Режим вывода информации о ходе выполнения программы ln . По-умолчанию, программой ln создаёт жёсткая ссылка. Жесткая ссылка на файл, ничем не отличается от исходного файла, при этом изменения сделанные в файле, не зависят от имени, по которому к нему было сделано обращение. Жесткие ссылки, не могут быть ссылками на каталоги, а так-же не могут находится за пределами данной файловой системы. Символическая ссылка содержит имя файла, на который ссылается. При выполнении операции open (2) над символической ссылкой используется ориги нальный файл. Вызов stat (2), выполненный над символической ссылкой, также вернёт исходный файл. Для получения информации о ссылке можно использовать lstat (2). Для чтения содержимого символической ссылки можно воспользоваться вызовом readlink (2). В отличии от жестких ссылок, символические, могут находиться на другой файловой системе и могут указывать на каталоги. С одним или двумя аргументами, программа ln создаёт ссылку на существующий исходный_файл . Имя для ссылки будет взято из аргумента целевой_файл . Если в аргументе целевой_файл , не указана директория для создания ссылки, будет использована текущая директория, если указан только каталог, будет создана ссылка на последний элемент из исходный_файл . С более чем двумя аргументами, программа ln создаёт ссылки в целевой_каталог на все указанные пути в исходный_файл . Ссылки при этом получают имена исходных файлов. Если программа ln , вызывается в форме link , ей передается ровно два аргумента, передаваемые аргументы не могут быть каталогами, кроме того, в данной форме она не принимает никаких опций. Это простая форма использования. Совместимость Опции -h , -i , -n и -v , предназначены для совместимости с другими реализациями программы ln , и не рекомендуются для использование в скриптах. Опция -F является дополнительной для

    • Сергей Савенков

      какой то “куцый” обзор… как будто спешили куда то