Allows you to use one WordPress installation for multiple sites at the same time. In this case, each site gets its own tables in the database with a unique prefix.

Tables with data of registered users are common for all network sites. This is a definite plus and by registering once you can get access to several sites. Moreover, on each site the same account can have different rights. For example, a user might be an editor on one site and an administrator on another.

In normal installing WordPress the registration, authorization and password reset page displays the wp-login.php file.

  • wp-login.php - authorization
  • wp-login.php?action=register - registration
  • wp-login.php?action=lostpassword - password reset

In Multisite mode, the WordPress core starts to behave a little differently and when you click on the wp-login.php?action=register link, it will redirect to wp-signup.php . This is your network registration page that comes with WordPress by default.

In addition to registering regular user accounts, you can also create a new site on it if the super administrator has enabled this feature in the network settings (Network Admin → Settings → Network Settings).

In most themes, the registration page does not look very good. Many themes use CSS frameworks like Bootstrap and their own specific classes to style different elements on the page, so it's hard to write a single HTML that fits everyone.

But do not despair if the page looks untidy. The wp-signup.php file is great at first, when you don't have time to work through every detail of the site - you can focus on other more important pages and content.

When you're ready to make your own signup page, wp-signup.php is a good reference and example to easily understand the range of features that WordPress provides for processing and validating user input and creating new accounts.

Network main site

By default, WordPress opens the signup page (wp-signup.php) on the main domain (website) of the web. However, you can create registration pages for every site in the network, even if they have themes.

We will consider the case when all sites in the network use the same theme, but each of them has a registration page. Sites differ in language (English and Russian), so the registration page will be displayed in the "native" language of the site. In case sites use different themes, it will all depend on which themes they are, whether the same layout is suitable for them (a great situation that can push you to unify all your themes) or whether it is worth developing pages individually.

functions.php alternative

File order

MU plugins can contain any number of files and structure that seems logical to you. I follow a hierarchy like this:

| mu plugins | | load.php | | selena network | | | sign up | | | | plugin.php | | | ... | | | jetpack | | | | plugin.php

In the load.php file, translations and all the necessary "plugins" are connected:

// Load translations for MU plugins load_muplugin_textdomain("selena_network", "/selena-network/languages/"); // Functionality for registration page require WPMU_PLUGIN_DIR . "/selena-network/signup/plugin.php"; // Another plugin // require WPMU_PLUGIN_DIR ...

Plugin folders are stored inside the selena-network directory. Each has its own plugin.php , which we include in load.php . This gives flexibility and the ability to instantly disable and enable individual components on the working project in case of emergency.

Registration page

Having figured out where and how we will write the code, we can move on to creating the registration page.

Let's create a page with the address example.org/signup/ through the usual interface. You can use any URL that seems appropriate for your project as the address.

Redirect to the required registration page

In order for WordPress to know about our new registration page and redirect to it, when clicking on the “Sign up” link, the wp_signup_location filter is used. It can be found inside wp-login.php and is responsible for redirecting to wp-signup.php by default.

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

As you remember, by default, the registration page opens on the main network domain. That is why network_site_url() is used here.

Let's add our handler to the filter in mu-plugins/selena-network/signup/plugin.php , which will give the address of the registration page on the current site:

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

selena_network is a prefix that I use in the names of all functions inside MU plugins on my site to avoid collisions, it should be replaced with my own unique prefix. Add filter priority 99 because some plugins like bbPress and BuddyPress can overwrite this address with their own (MU plugins are loaded before normal plugins, see above).

Note that home_url() is used, which, unlike network_site_url() , returns the address of the current site, not the main site of the network.

wp-signup.php functionality

The wp-signup.php file contains a lot of functions and code. To see the big picture, you can use code folding. As a rule, in English this is called "code folding".

At the very beginning of the file from lines 1 to 80 (in version 4.1.1) various checks and displaying the "start" of the page with get_header() .

Next, a lot of methods are declared, and before we start working with them, it's worth understanding what each function does. Many of them often use other functions prefixed with wpmu_ , all of which are declared in the wp-includes/ms-functions.php file. This section is hard to understand without seeing the code yourself. Below is a short description of the main functions in case you have any difficulties.

  • wpmu_signup_stylesheet() - Output additional CSS on the registration page.
  • show_blog_form() - fields for site registration (address, name, visibility for search engines).
  • validate_blog_form() - Validates the entered website address and title using wpmu_validate_blog_signup() .
  • show_user_form() - fields for user registration (login and email address).
  • validate_user_form() - validation of the entered login and email address. mail with wpmu_validate_user_signup() .
  • signup_another_blog() - fields for registering new sites using show_blog_form() for users who are already registered on the site.
  • validate_another_blog_signup() - Validates the site address and title with validate_blog_form() .
  • signup_user() is the main function for displaying the signup page fields.
  • validate_user_signup() - Validates username and email address. mail with validate_user_form() .
  • signup_blog() - fields for entering the address, name and visibility of the site (the second step of registration) using show_blog_form() .
  • validate_blog_signup() - validates the login, email address. mail, address and site name.

At the very bottom of the wp-signup.php file (from line 646 in version 4.1.1) is the main logic of the signup page, which uses all the methods described above. This part of the code is not moved into a function. At the end, get_footer() is called.

Copy the functionality of wp-signup.php

Next, the procedure for copying wp-signup.php to MU plugins and making changes to the "fork" will be described. Perhaps this may not seem like the right way. Instead, you can write your own functions for validating and displaying forms from scratch using classes rather than regular functions. In my opinion, wp-signup.php already has all the necessary logic for our page, it remains only to make small changes.

When updating WordPress, wp-signup.php also changes from time to time, but this does not mean that you will have to synchronize your “fork” with each release. The functions inside wp-signup.php basically do nothing but HTML output, data validation, account and site creation, and the wpmu_ prefixed methods declared in ms-functions.php .

Let's create a function that will display the registration form on the page. To do this, copy wp-signup.php from the WordPress root to mu-plugings/selena-network/signup/ . Connect it inside mu-plugins/selena-network/signup/plugin.php).

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

Remove all require and unnecessary checks from the very beginning of the copied file. In version 4.1.1, this is all the code from lines 1 to 80.

Now we are ready to create main function to display the registration form. To do this, we will transfer all the logic from line 646 to the very end of the file into a function called selena_network_signup_main . At the very end, we will remove two extra closing

(lines 722 and 723), as well as the call to get_footer() .

In the newly created selena_network_signup_main() , at the very beginning we will declare the global variable active_signup , which is used by all other methods from this file. And add a call to the before_signup_form event, which we removed from the very beginning of the file.

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

Now it remains only to change the layout in all places where it is necessary and the registration page is ready.

Registration form output

There are at least two options here. A more convenient way is to create a shortcode and place it on the page through a regular editor.

// Create shortcode network_signup add_shortcode("network_signup", "selena_network_signup_main");

The second option is to create a page template page-signup.php in your child theme folder. Instead of the word "signup", you can use a unique ID assigned to the page. Inside the template, add the necessary layout and make a call to selena_network_signup_main() in the right place.

As a result, my registration page looks much better and cleaner.

Activation page

By WordPress default conditionally divides the registration process in Multisite into two steps - filling out a form on the site and activating an account when clicking on a link sent in an email. After you fill out the form created in the previous section, WordPress sends an email with some instructions and a link to activate your account.

The wp-activate.php file located in the WordPress root directory is responsible for displaying the activation page. wp-activate.php can also be completely changed. The process is similar to what we already did for wp-signup.php .

Let's create the page example.org/activate/ through the usual interface. For the address, use any URL that seems appropriate to you.

Copy the wp-activate.php file to our MU plugins and include it in mu-plugins/selena-network/signup/plugin.php .

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

There isn't much content inside, unlike wp-signup.php . The file performs a single operation - it activates the account if the correct key is received and displays an error or success message.

Let's remove all unnecessary checks and require - lines 1 to 69 in WordPress 4.1.1. At the very end, we will remove the get_footer() call. The remaining content will be transferred to the selena_network_activate_main() function.

It's interesting to note that here, before loading WordPress (wp-load.php), the WP_INSTALLING constant was declared. Its presence causes WordPress not to load plugins.

As in the case of the registration page, it remains only to correct the layout where necessary. You can also change the text of displayed messages (in this case, do not forget to add the text domain of your MU plugins to all translator functions, it is not set anywhere by default).

The ready-made function can be used on a pre-created page through a shortcode or a separate template in a child theme.

Activation emails with correct links

The activation page is ready to go, but WordPress doesn't know about it and will still send activation emails with a link to wp-activate.php . Unlike wp-signup.php, there is no filter that would allow you to change the address. Instead, you need to write your own function that will send emails with the correct links.

At the time of filling and submitting the form on the page WordPress registration calls wpmu_signup_ user() or wpmu_signup_ blog() depending on the type of registration. Both functions create new record in the wp_signups table, filling it with the necessary content, among which is the account activation key.

After, depending on the function, wpmu_signup_ is called user _notification() or wpmu_signup_ blog _notification() . Both functions have similar functionality - they generate and send an email with an activation link, but they take different arguments. Both have filters to "capture" the event.

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

To activate accounts with the creation of a blog:

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

It remains only to write your own handlers, inside which send letters via wp_mail() , and at the very end be sure to give false so that WordPress does not send an activation letter twice - one is yours, the other is a default letter with a link to wp-activate.php .

Function selena_network_wpmu_signup_user_notification($user, $user_email, $key, $meta = array()) ( // Generate email header, body and headers // ... // Send email or add Cron task to send email wp_mail($user_email , wp_specialchars_decode($subject), $message, $message_headers); // Pass false so WordPress doesn't send activation email twice return false; ) add_filter("wpmu_signup_user_notification", "selena_network_wpmu_signup_user_notification", 10, 4);

If you are sending emails through an SMTP server or the number of registrations is very high, you should consider not sending emails instantly. Instead, you can add Cron jobs using WordPress Cron .

Closing access to wp-signup.php and wp-activate.php

Having created your own registration and activation pages, you may need to close the "originals". For example, if there are additional fields on the registration page that must be filled in. Also, many WordPress sites are subject to spam registrations.

To solve two problems in one action, you can ask Apache to return 404 in case of an attempt to open these pages. To do this, you just need to register a couple of additional RewriteRule in your configuration file or .htaccess .

RewriteEngine On RewriteBase / # Knowing regular expressions is never superfluous :) RewriteRule ^wp-signup\.php - RewriteRule ^wp-activate\.php - # BEGIN WordPress # Leave default WordPress rules :) # ... # END WordPress

Conclusion

For this and many other "problems" related to WordPress, there are many solutions on the Internet. For example, in order to create registration and activation pages, some suggest rewriting the original wp-signup.php and wp-activate.php . This should not be done, because if wordpress updates you will lose all changes made to the files, and you will also not be able to check the integrity of the kernel with .

When developing any add-on, theme, or solution, spend a little time getting to grips with what's going on inside WordPress. There are many useful debug tools for this.

P.S.

You can use the Multisite User Management plugin to automatically assign different roles to new users.

If you have any questions or difficulties during the creation of registration and activation pages after reading the article, leave a comment and we will definitely answer.

27.03.2015 27.03.2015

WordPress developer. He likes order in everything and to understand new tools. Inspired by the Symfony component architecture.

  • --- Select Warehouse --- Buffalo Grove IL 60089 USA(Buffalo Grove IL 60089 USA)) Chicago USA USA Tamara(16677 SW Blanton street ALOHA. Oregon 97078) Highland Park(USA Highland Park , IL 60035 P.O Box 723 No.24) Istanbul(Istanbul,Gençturk Cad.15, Bırlik Han. k-5.d.55 No.1) Madrid 92200 Neuilly-sur-Seine) Republica Moldova , Falesti(s.Fagadau) South Kensington(Bute street) Adler(Quiet lane 2, Kudepsta district) Aktobe(47/2 Aktobe street) Almetievsk(Almetievsk, Lenin street 13, office 306) Anapa (88 Terskaya St., 3rd floor) Astrakhan (17 Kommunisticheskaya St., office 4) Atyrau (Atyrau, Azattyk Ave. 42, office 206) Berdyansk (Zaporozhye region) Bishkek ( Bishkek, 32B Chui avenue, shopping center "Izumrud" office C-5) Blagoveshchensk (50 Let Oktyabrya st. 15. "Amur Fair" office 575) Buguruslan (Krasnoznamnaya st. Krasnaya st., 61 (2nd floor) city center) Vladivostok (147 Svetlanskaya st., office 2/4) olgograd (city of Volgograd highway Aviators 15 warehouse 23) Dyurtyuli (st. Agidel, 4 kv.2) Yeysk (st. Pervomayskaya 56, office 308) Yekaterinburg (10 Mamin-Sibiryak St., office 3) Ivanovo (Sheremetevsky prospect, 85G, Premium Plaza Business Center 2nd floor, office 212) Izhevsk (Lenina 21, office 304. Business Center " Forum") Izberbash (Chapaeva 4 ind. 368501) Irkutsk (Irkutsk, Gornaya st. 4 (next to the Karamel shopping center) office 407) Ishimbay (Zorge, house 18) Yoshkar-Ola (24v Lenin Ave., office 318) Kazan ( lane One-sided Grivki house 10, metro station "Kozya Sloboda" also Dekabristov street, 85 "B" Business center "Relita" office 411) Kamensk-Uralsky (Prospekt Pobeda 56) Kemerovo (Demyan Bedny st., 1 office 401) Kyiv (Olevskaya st. 9 kv.4 (arrive by prior call) Komsomolsk-on-Amur (Shikhanova st. 10, office 1 entrance from Komsomolskaya from the end of the building.) Kostroma (Prospect Mira 51, office 15) .Krasnaya 124 office 302) Krasnoyarsk (pr. Krasnoyarsky worker, 120 shopping center "Krasnoyarye") Lviv (Sobornaya Square 12A) Makhachkala (Akushkinogo 9v) Miass (st. 30 let VLKSM 85) Minsk (Korzhenevskogo, 26) Moscow (Metro :VDNH, Yaroslavskaya st., 10, building 4, office 10 6) Moscow (Simferopolsky Boulevard) Moscow (Glazovsky lane 5, entrance in the arch, the door on the left of the metro station: Smolenskaya-500m, Kropotkinskaya-1km., Park Kultury-1km.) Moscow (m. Chekhovskaya, Pushkinskaya, Tverskaya. Strastnoy Boulevard, 6, building 1, Business Center, office 421) Moscow (Lobnya, Mayakovskogo st., 4A, TR1, 3rd floor, office 301) Moscow (Molodezhnaya metro station, Yartsevskaya street, 27 building 9 Health-improving Center "Four Elements") Moscow (Krasnaya Presnya 38-45) Moscow (St. Moscow m. Taganskaya radial exit 3, 30 meters from the metro. st. Bolshiye Kamenshchiki 1, 4th floor, office 30) Moscow (metro station Leninsky Prospekt, Vavilova 9A, building 6, office 10 B, 3rd floor) Moscow (metro station Novoslobodskaya, Mendeleevskaya, Mayakovskaya, Belorusskaya (radial). 4th Tverskaya street -Yamskaya, 24. Entrance through the arch, PET SHOP) Moscow (metro Belorusskaya (ring), 5 meters from the metro exit. Tverskaya Zastava Square, 3, 3rd floor, office 321. Near the Belorussky railway station. ) Moscow (M. ALTUFIEVO, Pskovskaya st., 6) Moscow (Moscow, Radio st. , entrance 2, office 2) Naberezhnye Chelny (Sh.Usmanova st. 122 kb. 111 1st floor) Nalchik (Nalchik, Kirov st. 292a, 2nd floor, office 6) Nakhodka (Pogranichnaya st. 6, room 304) Nevinnomyssk (Pl. 50 Let Oktyabrya 8A) Nefteyugansk (12 microdistrict house 7) Nizhnevartovsk (Nizhnevartovsk, Mira st. 31B.) Nizhny Novgorod (Comintern st. 139, office 603 (OREOL business center)) Nizhny Novgorod (m. Gorkovskaya, st. Kostina 3, BC "New Square", 2nd floor, office 239) Nizhny Tagil (at l. Krasnoarmeyskaya d.42a, 3rd floor office 4) Nizhny Tagil (Nizhny Tagil, st. Papanina 5, office 1, Kushva, Gornyakova st. 2/11) Nikolaev (Ryumin st. 5/1) Novorossiysk (Krasnodar Territory, Novorossiysk, Tsemdolina village, Zolotaya Rybka st., 15) Novorossiysk (Murat Akhedzhak st., d. 4) Novosibirsk (Street, Oktyabrskaya 42 office 601, Business center approximately Lenin Square, Mayakovsky cinema) Novosibirsk (Gogol street 33/1. 20 meters from the Marshal Pokryshkina metro station, Gogol shopping center.) Novotroitsk (Sovetskaya d st. .144 sq. 26) Novy Urengoy (microdistrict Druzhba, house 4/3, apt. 183) Norilsk (Leninsky prospekt 47a of. 79) Nur-Sultan (Astana) (Beibitshilik 14, BC Marden, office 708) Odessa (b -R French 60 multidisciplinary rehabilitation sanatorium "SARTUS") Oktyabrsky (Microdistrict 32a, house 6, apt. 88) Omsk (5 Severnaya st. first floor, right porch.) Orsk (Lenin Ave. 93) Pavlodar (Satpaev St. 71 office 107) Perm (Sovietskaya d.52 office 1) Perm (Druzhby St. 34 office 305) Pyt-Yakh (Microdistrict 5, house 5) Pyatigorsk (str. 295 Rifle Division and 13 k.2) Rostov-on-Don (Soborny lane 21 office 10 B) Salavat (Lenina street, building 3 office 209, 2nd floor) Samara (Novo-Sadovaya street 106, office 804, left elevator, 8th floor) St. Petersburg (metro: Vasileostrovskaya, 13th line of Vasilyevsky Island, 78, office 182) St. Petersburg (metro station Dostoevskaya (5 meters) and metro station Vladimirskaya (300 meters) VLADIMIRSKY PASSAGE 3rd floor, central entrance FIRST GALLERY, ave. Vladimirsky 19) Saint Petersburg (metro station Admiralteyskaya (10 meters) Spasskaya 1 min walk Efimov St. 1, floor 2, office 4, Business Center "Sennaya 4", entrance to the left of the cafe "Sever") Saratov (Bolshaya Gornaya St., 359V, office No. 3) Sevastopol (Ochakovtsev St. 19 , center "Plaza", ground floor, office 29/2) Snezhinsk (Zababahina st. 19 a) Sochi (Sochi ko. Donskaya house 15.) Sochi (Sovetskaya st. 42 office 204) Stavropol (Lomonosov st. 21 office 18) Sterlitamak (85 Khudaiberdina St., 3rd floor) Surgut (30 let Pobedy St. 64) Tobolsk (Tobolsk, microdistrict 6, building 11, office 39 (entrance from Komsomolsky Prospekt)) Togliatti (40 years old) Pobedy, 50, office 212a, TD Raduga 1st floor) Tomsk (Tomsk, Sovetskaya street 84) Tuymazy (Michurina street, 15 office 2) Tyumen (Gerzen street, 72 office 214) Ulyanovsk (Ryabikov street, d 73) Ust-Kamenogorsk (57 Gorky St., office 213) Ufa (Verkhnetorgova Square, 6 (Business Center NESTEROV)) Khabarovsk (Postysheva St., 16 office from 108) Khanty-Mansiysk (G. Khanty-Mansiysk, st. Karl Marx 15, 2nd floor.) Chelyabinsk (168 Pobedy Ave., 3rd floor, office 36.) Cherkessk (101 Lenina St.) Chita (104 Babushkina St., office 425) Chishmy (17 Ring Road) Chishmy (Friendship Ave. , 1B) Switzerland (Arosio via Terra Sotto, 1 6939) Shymkent (Kolkhoznaya st. 47) Yuzhno-Sakhalinsk (Angarsky lane 21) Yakutsk (Dzerzhinsky st. 8 / 3b) Yakutsk (Yakutsk) Yalta (Lenin embankment, 5a, SEC "Fountain, 4th floor) Yanaul (street Sovetskaya, 23, office N 8 building Berezka) Yaroslavl (57 Showroom) Yaroslavl (street Chkalova 2) Birsk Bashkortostan () ?>

    The question often arises as to how to place one form on all pages of your Zend application. Let's say I want to place the subscription form in the layout.phtml file so that it is located on every page. The layout->content() command works with actions and controllers... So how do we implement what we need?

    One solution to this problem is to create an action helper.

    Let's start by setting up the ZF application:

    $ zf create project layout form $ cd layout form $ zf enable layout

    Clean up the application/views/scripts/index/index.phtml file and paste something like this:

    application/views/scripts/index/index.phtml:

    This is the home page

    Now we can start.

    The form

    Let's create new form:

    $ zf create form signup

    As well as the fields that we need:

    application/forms/Signup.php:

    Class Application_Form_Signup extends Zend_Form ( public $processed = false; public function init() ( $this->addElement("text", "name", array("label" => "Name", "required" => true, " validators" => array(array("StringLength", false, array("max"=>75)))),)); $this->addElement("text", "email", array("label" = > "Email", "required" => true, "validators" => array(array("StringLength", false, array("max"=>150)), "EmailAddress",),)); $this- >addElement("submit", "go", array("label" => "Sign up",)); ) )

    We have a form. It remains to bring it out.

    Action Helper

    We use the action helper to initialize the form.

    Add a line to application.ini:

    application/configs/application.ini:

    Resources.frontController.actionhelperpaths.Application_Controller_Helper = APPLICATION_PATH "/controllers/helpers"

    Now the system knows where to look for action helpers, so we can move on:

    application/Bootstrap.php:

    bootstrap("frontController"); $signup = Zend_Controller_Action_HelperBroker::getStaticHelper("Signup"); Zend_Controller_Action_HelperBroker::addHelper($signup); ) )

    The action helper will look like this:

    application/controllers/helpers/Signup.php:

    getActionController()->view; $form = new Application_Form_Signup(); $request = $this->getActionController()->getRequest(); if($request->isPost() && $request->getPost("submitsignup")) ( if($form->isValid($request->getPost())) ( $data = $form->getValues() ; // process data $form->processed = true; ) ) $view->signupForm = $form; ) )

    There is nothing special here. Just pay attention to the parent class.

    View helper

    To display the form, let's create a view helper that looks like this:

    application/views/helpers/SignupForm.php:

    Sign up for our newsletter

    "; if($form->processed) ( $html .= "

    Thank you for signing up

    "; ) else ( $html .= $form->render(); ) return $html; ) )

    All that's left for us is to render the form in layout.phtml:

    application/layouts/scripts/layout.phtml:

    headMeta()->prependHttpEquiv("Content-Type", "text/html; charset=UTF-8"); $this->headTitle("Layout form test"); echo $this->doctype(); ?> headMeta()->setIndent(4); ?>headTitle()->setIndent(4); ?>

    layout()->content; ?>
    signupForm($this->signupForm); ?>

    Happened

    That's all. We have achieved the functionality we envisioned.

    Cm … Synonym dictionary

    BAINKI, unchanged. ch. (childish). Sleep. Do you want boobies? Lie down bainki. Explanatory Dictionary of Ushakov. D.N. Ushakov. 1935 1940 ... Explanatory Dictionary of Ushakov

    Do / do bainki (bye bye). Jarg. they say Shuttle. Sleep. Maksimov, 21 … Big dictionary of Russian sayings

    I predicate. unfold About the state of sleep (in children's speech or in the conversation of adults with children). II int. unfold Used as a component of a lullaby. Explanatory Dictionary of Ephraim. T. F. Efremova. 2000... Modern dictionary Russian language Efremova

    bainki- ainki, immutability ... Russian spelling dictionary

    bainki- immutability ... Spelling Dictionary of the Russian Language

    Intl., in funkt. skaz. \u003d Bai Bai (II sign) ... encyclopedic Dictionary

    bainki- int.; in func. skaz. = bye bye 2) … Dictionary of many expressions

    bainki- ba / ink / and, between ... Morphemic spelling dictionary

    Books

    • Bainki, Tokmakova I.P. In this book you can read or even sing lullabies for your baby. Cut out book...
    • Bainki (2006 ed.), Irina Tokmakova. In this book, you can read or even sing lullabies to your baby. Cut out book. ISBN:5-9524-2404-X…

    Let's create our own multisite registration page instead of the standard wp-signup.php .

    AT normal installation wordpress page registration (authorization, password reset) outputs the wp-login.php file.

    • /wp-login.php - authorization
    • /wp-login.php?action=register - registration
    • /wp-login.php?action=lostpassword - password reset

    There are separate conditions for multisite in wp-login.php. So, when you click on /wp-login.php?action=register on a multisite, WordPress will redirect to the /wp-signup.php page. In many themes, the page does not look very attractive, so we will make our own.

    Network main site

    By default, WordPress opens the signup page (wp-signup.php) on the main domain (website) of the web. However, it is possible to make a separate registration page for each site in the network, even if they have different themes. We will consider the case when all sites in the network have their own registration page, but the same theme is used and the sites differ only in language. If different themes are used, more code will be required.

    functions.php?

    No. The name of this file seems to be mentioned in every WordPress article. In our case, taking into account the fact that the registration functionality is designed for several sites, it makes sense to move it to MU plugins that are loaded when any site is opened.

    Lyrical digression

    It is worth noting that MU plugins are loaded before normal plugins and before the WordPress core is fully loaded, so calling some functions can lead to fatal errors in PHP. This "early" loading has its advantages. Let's say inside any theme you can't cling to some actions that work even before the functions.php file is loaded from the theme. An example of this is actions from the Jetpack plugin of the form jetpack_module_loaded_related-posts (related-posts is the name of the module) with which it is possible to track the activity of modules in Jetpack. This action cannot be "attached" from the theme file because the action has already fired before the theme is loaded - plugins are loaded before themes. You can take a look at a general picture of the WordPress load order on the Action Reference page in the codex.

    File order

    MU plugins can contain any number of files and any structure that seems logical to you. I follow a hierarchy like this:

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

    In the load.php file, all the necessary "plugins" for our network are connected:

    // 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 ...

    Plugin folders are stored inside the selena-network folder, each has its own plugin.php , which we include in load.php . This gives flexibility and the ability to quickly disable and enable certain things.

    Registration page URL

    The wp_signup_location filter is used to specify the signup page address. It can be found inside the wp-login.php file and is responsible for redirecting to wp-signup.php .

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

    Let's add our function to mu-plugins/selena-network/signup/plugin.php , which will give the address of the registration page on the current site:

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

    selena_network is a prefix that I use in the names of all functions inside MU plugins on my site to avoid collisions, it should be replaced with your own unique prefix. Add filter priority 99 because some plugins like bbPress and BuddyPress can overwrite this address with their own (MU plugins are loaded before normal plugins, see above). Note that home_url() is used instead of network_site_url() to keep the visitor on the same domain. Any URL can be used as the address.

    Page creation

    Now we will create a page with the address site.com/signup/ through the usual interface, and in the child theme folder a template for our new page- page-signup.php . Instead of the word "signup" you can use a unique ID.

    Inside the new template, you need to call the selena_network_signup_main() function, which will display the registration form.

    It is worth noting that the whole process with templates is optional and instead you can create your own shortcode, which will also call the selena_network_signup_main() function.

    wp-signup.php and wp-activate.php

    Now let's create a function that will display the registration form. To do this, copy the wp-signup.php and wp-activate.php files from the WordPress root to mu-plugings/selena-network/signup/ (and don't forget to include them inside mu-plugins/selena-network/signup/plugin.php) . Further file manipulations are extremely difficult and long to describe, so you will have to do them yourself. I will just describe what exactly needs to be done and publish source files of your project:

    1. At the beginning of the file, remove all require , function calls, and other code outside of functions.
    2. Rename all functions by adding unique prefixes to the names.
    3. Wrap the bottom part of the wp-signup.php code in the selena_network_signup_main function and write global $active_signup at the very beginning; .
    4. Replace the layout with your own in the right places.

    Inside wp-activate.php you need to do the same thing:

    1. Remove all code outside of functions, wrap the layout in a separate function.
    2. Change layout where needed.

    The wp-activate.php file is responsible for the account activation page. As with the registration page, you need to create a separate template for it, inside which you need to call the function from the wp-activate.php file.

    Sending activation emails

    The registration page sends an email to the visitor with a link to activate the account. By default, this is handled by the wpmu_signup_user_notification() function from the ms-functions.php file. Its functionality can be borrowed for its function. The reason you need to stop using this feature is that it sends an account activation link from wp-activate.php . You can “turn off” this function using the wpmu_signup_user_notification filter by giving it false (if this is not done, the activation letter will be sent twice, ok, actually two different letters).

    Function armyofselenagomez_wpmu_signup_user_notification($user, $user_email, $key, $meta = array()) ( // ... // Code from wpmu_signup_user_notification() function 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);

    As a result, the registration page in the Selena theme has become much cleaner and neater.

    Conclusion

    There are many other not very correct ways on the Internet how to do the same - Apache redirects, AJAX forms that will not work without Java Script, etc. I didn’t really like all this, so I tried to do it as correctly as possible on my own site.

    I note that you should edit the files carefully and try not to deviate too much from the original ones, so that in the future, if WordPress changes the wp-signup.php and wp-activate.php files, it would be easier to compare them to find changes.

    Don't forget to look at source all the functions described above in order to fully understand what and how happens inside the code.

    Bonus. Spammer Protection

    Even the smallest WordPress sites are often bombarded with spam registrations. You can write endless conditions for filtering bots, often more like trying to create artificial intelligence 🙂 In the case of a multisite, the usual redirect in Apache helped me a lot, with which I asked to issue 404 when opening /wp-signup.php and /wp-acitvate.php (I'm not an Apache setup expert, so my rules may not be very correct).

    RewriteEngine On RewriteBase / RewriteRule ^wp-signup\.php - RewriteRule ^wp-activate\.php - # BEGIN WordPress # Default WordPress rules :) # ... # END WordPress

    P.S. I try to describe some third-party things in as much detail as possible, because when I started, sometimes there was no one to prompt and explain many things. I also believe that such small tips on other materials will push someone to learn something new and expand their area of ​​​​knowledge. RewriteRule entries use regular expressions, they are not complicated at all, for example, the ^ symbol means the beginning of a line.