├── .gitmodules ├── README.md ├── changelog.txt ├── humans.txt ├── inc └── sunrise.php ├── js └── placement.js ├── languages ├── multi_domain-en_US.mo └── multi_domain-en_US.po ├── multi-domains-sso.php ├── multi-domains-table.php ├── multi-domains.php └── sunrise.php /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "extra"] 2 | path = extra 3 | url = git@github.com:wpmudev/wpmudev-dashboard-notification.git 4 | branch = master 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multi Domains 2 | 3 | **INACTIVE NOTICE: This plugin is unsupported by WPMUDEV, we've published it here for those technical types who might want to fork and maintain it for their needs.** 4 | 5 | ## Translations 6 | 7 | Translation files can be found at https://github.com/wpmudev/translations 8 | 9 | ## Multi-Domains adds the power to operate multiple primary domain names on a single WordPress Multisite network. 10 | 11 | It's like having multiple networks on one Multisite installation – but better. 12 | 13 | ![multi-domain735x470](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domain735x470-583x373.jpg) 14 | 15 | Offer relevant URLs to more users on one network. 16 | 17 | ### More Network URLs to Choose From 18 | 19 | Give users the ability to choose a network domain that relates to their business, site or service or let users easily create a niche blog and select a content relevant URL. Add full domain control and flexibility without creating a new network. 20 | 21 | ### Global Login Sync 22 | 23 | Enable single sign-on sync and pass from site to site without having to login everytime you change domains. Provide fast user access to all the content on your network. 24 | 25 | ### More Name Options 26 | 27 | Automated page configuration and a powerful single-settings page have Multi-Domains working perfectly out-of-the-box. Add domains using the domain manager and the new host URL options will be automatically added to the Site Sign-up form. 28 | 29 | ![users-choose-735x470](https://premium.wpmudev.org/wp-content/uploads/2010/09/users-choose-735x470-583x373.jpg) 30 | 31 | Give users more choices and add value to your network. 32 | 33 | ### Level-Up With Domain Mapping and New Blog Template 34 | 35 | Integrate Multi-Domains with [Domain Mapping](http://premium.wpmudev.org/project/domain-mapping/) and offer your users a completely custom url. Plus, with [New Blog Templates](http://premium.wpmudev.org/project/new-blog-template/ "New Blog Templates") you can set unique default themes for each host domain. 36 | 37 | ## Usage 38 | 39 | **Please note:** Multi-Domains is for sub domain installations only and will not work well for subdirectory installations. Other important notes: 40 | 41 | * As of Multi-Domains version 1.3, it is no longer necessary to manually install the plugin in the mu-plugins folder. Woot! If you have an older version in that folder now, please remove it. 42 | * It is also no longer necessary to manually update the sunrise.php file as that is now done automatically. :) 43 | * Finally, if you are also using our Domain Mapping plugin, be sure that it is at least version 4.0.3. 44 | 45 | ### To Get Started 46 | 47 | Start by reading [Installing plugins](../wpmu-manual/installing-regular-plugins-on-wpmu/) section in our comprehensive [WordPress and WordPress Multisite Manual](https://premium.wpmudev.org/manuals/) if you are new to WordPress. Once installed and network-activated, you will see a new menu item in the Network Settings menu. 48 | 49 | ![Multi-Domains Menu](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1310-menu.png) 50 | 51 | #### Configuring the Settings 52 | 53 | The first thing you need to do is add a constant to your _wp-config.php_ file. Please copy the sunrise.php from the plugin folder /FOLDER-PATH/wp-content/plugins/multi-domains/sunrise.php into /FOLDER-PATH/wp-content/sunrise.php Then open your _wp-config.php_ file (normally located in the root of your install) and please uncomment or add (if not available) the following code just before the line that says "That's all, stop editing!": `define( 'SUNRISE', 'on' );` 54 | 55 | ![multi-domains-1300-wpconfig](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1300-wpconfig.png) 56 | 57 | Please ensure that you type this and not just copy and paste. Take care to use single quotes and not back-ticks. Save and re-upload that file. Now head over to the Multi-Domains page in your Network Admin area at Settings > Multi-Domains 58 | 59 | ![Multi-Domains Settings](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1310-settings.png) 60 | 61 | There, you can add all the domain names you want to include in the selection for new sites in your network. Simply enter the name, select Public or Private, and click Add Domain. Done. Note that domains set to Private will be available to the network admins only. Domains set to Public will be displayed on your user and blog registration pages. Bonus! If you have the [New Blog Templates](https://premium.wpmudev.org/project/new-blog-template/ "WordPress New Blog Templates Plugin - WPMU DEV") plugin installed, you can also select which template to use for each domain. Cool huh? The final step is domain name configuration in your hosting to make sure the blogs created work. 62 | 63 | ### Domain Configuration 64 | 65 | In the DNS records for each domain added, add a wildcard subdomain that points to the IP of your WordPress multisite. You simply need to add an "A" Record by entering an asterisk for the name, and the IP of your multisite for the address. For example, here's a domain configured with a wildcard subdomain through cPanel: 66 | 67 | ![multi-domains-1300-wildcard](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1300-wildcard.png) 68 | 69 | ### Deleting Previously Added Domains: 70 | 71 | Hover your mouse pointer over the domain name in the list and click the Delete link which appears. 72 | 73 | ![Multi-Domains Delete](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1310-delete.png) 74 | 75 | If you want to do a batch delete of several domains, check the boxes next to the domains names and click the Delete button . 76 | 77 | ### Changing a domain status: 78 | 79 | You may want to change the status (public or private) of a domain name. 1\. Hover the domain name in the list and click the Edit link which appears. 2\. Select a new status. - Choose Public if you want it to be available to all the users who register on your blog. - Choose Private if you want it to be used by Super Admins only. 3\. Click Save Domain. 80 | 81 | ### Creating Sites in the Admin 82 | 83 | Now when you go to Sites > Add New in your network admin, you'll see a new option to select which domain you want to add the new site to. 84 | 85 | ![Multi-Domains Add Site](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1310-add-site.png) 86 | 87 | ### User Experience 88 | 89 | Users who wish to create a blog in your network can now select from the domains you have made available to them when they sign up. 90 | 91 | ![Multi-Domains Signup](https://premium.wpmudev.org/wp-content/uploads/2010/09/multi-domains-1310-signup-2.png) 92 | 93 | ### Potential Issues 94 | 95 | Many times you may run into trouble where mapped domains don't resolve to your WordPress Multi-site install even though the DNS is correct for the domain you are trying to map. This is especially common with shared hosting. Some symptoms are getting a default or non-existent domain screen branded by your host. What this means is that your WordPress install/virtualhost is not set as the default for your IP address, so different domains do not load it up. Here is a very simple way to check if your hosting is configured correctly: Simply enter your server's IP address into a web browser and see if it loads up your WordPress signup page. For example, using the Edublogs IP you would enter http://66.135.63.39 into the web browser. See how it loads up the signup page? If entering your IP pulls up an error screen from your host (Example: http://74.54.219.243) here is what you can do: 1\. Purchase a dedicated IP address for your hosting. 2\. Many times just the dedicated IP will do the trick. If not, you will need to ask your host to configure your WPMU virtualhost to be the default for your dedicated IP. 3\. If you have addon domains in your hosting account, this may cause additional issues. To resolve this, you could add the domain you want to offer as a parked domain. Then create a wildcard A record in your DNS zone editor and point it to your dedicated IP as shown above. 96 | 97 | * Note that any DNS edits may take up to 48 hours to propagate. 98 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- 1 | == 1.3.4.5 == 2 | * Fixed: Incorrect or out of date cookie nag 3 | 4 | == 1.3.4.4 == 5 | * Fixed: vulnerability in add_query_arg and remove_query_arg usage 6 | * Fixed: Wildcard DNS Availability check 7 | 8 | == 1.3.4.3 == 9 | * Amended: sunrise inclusion 10 | 11 | == 1.3.4.2 == 12 | * Changed how sunrise is maintained 13 | 14 | == 1.3.4.1 == 15 | * Deprecated multi_domain::restore_current_site() 16 | * Fixed bug with outgoing emails on new site creation 17 | 18 | == 1.3.4 == 19 | 20 | * Added sso for logging to main domain from secondary domains 21 | 22 | == 1.3.3 == 23 | 24 | * Added Multidomains_Sso 25 | * Fixed cross domain single signon issue 26 | * Fixed cross blog single signon issue 27 | 28 | == 1.3.2.1 == 29 | 30 | * Fixed minor bug with wrong message in the instructions section. 31 | 32 | == 1.3.2 == 33 | 34 | * Fixed site creation issue which appears when trying to create a site via admin dashboard 35 | 36 | == 1.3.1 == 37 | 38 | * Reworked network admin domains page 39 | * Improved performance for case when a lot domains are added 40 | * Fixed minor issues 41 | * Fixed sunrise.php compatibility issue 42 | * Integrated new WPMUDEV dashboard notifications class 43 | 44 | == 1.3 == 45 | 46 | * Reworked the multi-domains plugin to work from plugins directory 47 | * Implemented functionality to auto copy/upgrade sunrise.php file 48 | 49 | == 1.2.3 == 50 | 51 | * Updated the sunrise. 52 | 53 | == 1.2.2 == 54 | 55 | * Updating sunrise. 56 | * Forcing empty values existence. 57 | 58 | == 1.2.1 == 59 | 60 | * Placement script scoping. 61 | * Blog selection issue fix. 62 | 63 | == 1.2 == 64 | 65 | * Domains site search. 66 | * Stuck transients issue fix. 67 | * BuddyPress cross-domain login issue fix. 68 | 69 | == 1.1.6 == 70 | 71 | * Better selection block placement. 72 | 73 | == 1.1.5 == 74 | 75 | * Fix for new site creation on sub-blogs. 76 | 77 | == 1.1.4 == 78 | 79 | * Fix for re-auth required on first login issue. 80 | 81 | == 1.1.3 == 82 | 83 | * Enhancement: performance improvements 84 | * Bug fix: incorrect domain used on site creation in network admin 85 | 86 | == 1.1.2 == 87 | 88 | * New Feature: Option to enable/disable single sign-on 89 | 90 | == 1.1.1 == 91 | 92 | * Enhancement: 3.1+ compatibility 93 | * Enhancement: Allow disabling cross domain login with a constant 94 | 95 | == 1.1 == 96 | 97 | * Enhancement: More extensible code with new hooks and structure 98 | * Bug fix: Allow www in mapped domain name 99 | 100 | == 1.0.9 == 101 | 102 | * Enhancement: Better compatibility with Domain Mapping for subdomain installs 103 | 104 | == 1.0.8 == 105 | 106 | * Enhancement: Keep selected domain after signup error 107 | * Enhancement: Don't redirect to main site when a multi-domain is also a mapped domain 108 | * Enhancement: Don't display php error when sunrise.php does not find any multi-domain 109 | * Bug fix: Domain Mapping sunrise.php overwriting the global $current_site 110 | * Bug fix: Cookies stylesheets return 404 111 | 112 | == 1.0.7 == 113 | 114 | * Bug fix: domain choice field does not appear on site admin sites page 115 | * Enhancement: check if COOKIE_DOMAIN is already defined 116 | 117 | == 1.0.6 == 118 | 119 | * Bug fix: domain choice field appears on site admin blog edit page 120 | * Bug fix: improper redirection when the main site url start with www 121 | * Bug fix: authentification cookie not set when uppercase letters in the domain name 122 | * Enhancement: display domain names in alphabetical order 123 | 124 | == 1.0.5 == 125 | 126 | * Bug fix: domain choice field appears on site admin blog edit page 127 | 128 | == 1.0.4 == 129 | 130 | * Bug fix: no error message displayed when and existing user tries to register a blog with a name already used 131 | * Bug fix: incorrect admin help text and wildcard subdomain warning with subdir installs 132 | 133 | == 1.0.3 == 134 | 135 | * Fixed issue with blog registration on subdomains installs 136 | 137 | == 1.0.2 == 138 | 139 | * Fixed issue when dashboard site is defined. 140 | * Fixed 301 redirects from addon domains to main site. 141 | * Add IIS support for redirects from addon domains to main site. 142 | 143 | == 1.0.1 == 144 | 145 | * Added domain field to BuddyPress registration page. 146 | * Fixed compatibility issue with Anti-Slog plugin. 147 | 148 | == 1.0.0 == 149 | 150 | * Added domain field to the Add Site for on Super Admin > Multi-Domains page. 151 | 152 | == Beta 2 == 153 | 154 | * Used load_muplugin_textdomain() and load_plugin_textdomain() for translation. 155 | * Added 'md_show_restricted_domains' filter hook. 156 | * Added main site as default when plugin is activated. 157 | 158 | == Beta 1 == 159 | 160 | * Fixed bug that shown double site name in the activation mails. 161 | * Added instructions on the settings page. -------------------------------------------------------------------------------- /humans.txt: -------------------------------------------------------------------------------- 1 | /* TEAM */ 2 | Developer: Ulrich Sossou 3 | Location: Cotonou, Benin 4 | Twitter: @sorich87 5 | 6 | Developer: Eugene Manuilov 7 | Location: Kiev, Ukraine 8 | Contact: eugene[at]incsub[dot]com 9 | Twitter: @eugene_manuilov 10 | 11 | Developer: Sam Najian 12 | Location: Tehran, Iran 13 | Contact: sam[at]incsub[dot]com 14 | Twitter: @samnajian -------------------------------------------------------------------------------- /inc/sunrise.php: -------------------------------------------------------------------------------- 1 | get_var("SELECT `meta_value` FROM " . $wpdb->sitemeta ." WHERE `meta_key`='active_sitewide_plugins'") ); 7 | wp_cache_set("dm_active_plugins", $dmmd_active_plugins); 8 | } 9 | return is_array($dmmd_active_plugins) ? in_array("multi-domains/multi-domains.php", array_keys( $dmmd_active_plugins )) : false; 10 | } 11 | 12 | function multi_domains_sunrise() { 13 | global $wpdb; 14 | 15 | // set multi-domains sunrise version 16 | define( 'MULTIDOMAINS_SUNRISE_VERSION', '1.0.1' ); 17 | 18 | if ( defined( 'COOKIE_DOMAIN' ) ) { 19 | if ( defined( 'DOMAIN_MAPPING' ) || defined( 'DOMAINMAPPING_SUNRISE_VERSION' ) ) { 20 | // don't do anything if domain mapping has already processed the domain 21 | return; 22 | } else { 23 | // die if cookie domain has been set 24 | wp_die( 'The constant "COOKIE_DOMAIN" is defined (probably in wp-config.php). Please remove or comment out that define() line.' ); 25 | } 26 | } 27 | 28 | // setup current domain 29 | $using_domain = preg_replace( "/^www\./", "", $_SERVER['HTTP_HOST'] ); 30 | if ( preg_replace( '/^www\./', '', DOMAIN_CURRENT_SITE ) !== $using_domain ) { 31 | $md_domains = @unserialize( $wpdb->get_var( "SELECT meta_value FROM {$wpdb->sitemeta} WHERE meta_key = 'md_domains' AND site_id = 1" ) ); 32 | if ( is_array( $md_domains ) ) { 33 | if ( $_SERVER['REQUEST_URI'] == '/' ) { 34 | foreach ( $md_domains as $domain ) { 35 | if ( $_SERVER['HTTP_HOST'] == strtolower( $domain['domain_name'] ) ) { 36 | $location = 'http://' . DOMAIN_CURRENT_SITE; 37 | $m_iis = strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS' ) !== false; 38 | $dev_server = strpos( $_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer' ) !== false; 39 | if ( $m_iis || $dev_server ) { 40 | header( "Refresh: 0; url=$location" ); 41 | } else { 42 | header( "Location: $location", true, 301 ); 43 | } 44 | 45 | exit; 46 | } 47 | } 48 | } 49 | 50 | foreach ( $md_domains as $domain ) { 51 | if ( preg_match( '|' . strtolower( $domain['domain_name'] ) . '$|', $using_domain ) ) { 52 | define( 'COOKIE_DOMAIN', '.' . strtolower( $domain['domain_name'] ) ); 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | } 59 | 60 | // run sunrise 61 | if( multi_domains_is_md_active() ) 62 | multi_domains_sunrise(); -------------------------------------------------------------------------------- /js/placement.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | $(function () { 3 | 4 | var $name = $("#blogname"); 5 | var $domain = $("#domain"); 6 | var $suffix = false; 7 | 8 | function update_text () { 9 | if (!$suffix || !$suffix.length) return; 10 | var $strong = $suffix.find('~p').has("strong").find("strong"); 11 | if (!$strong.length) return; 12 | 13 | $strong.text( 14 | l10nMd.your_address + ' ' + $name.val() + '.' + $domain.val() 15 | ); 16 | } 17 | 18 | // Init 19 | if ($name.length && $domain.length && $domain.is("select")) { 20 | $suffix = $name.next(".suffix_address"); 21 | if (!$suffix.length) return false; 22 | 23 | $suffix.html('.').append($domain); // Move domain selection 24 | update_text(); // Update text 25 | 26 | // Bind handlers 27 | $name.change(update_text); 28 | $domain.change(update_text); 29 | } 30 | 31 | 32 | }); 33 | })(jQuery); -------------------------------------------------------------------------------- /languages/multi_domain-en_US.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wpmudev/multi-domains/fbb4620d2224c458559a6972eb031aecd838e217/languages/multi_domain-en_US.mo -------------------------------------------------------------------------------- /languages/multi_domain-en_US.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: Multi-Domains for Multisite\n" 4 | "POT-Creation-Date: 2014-09-21 17:17+0330\n" 5 | "PO-Revision-Date: 2014-09-21 17:18+0330\n" 6 | "Last-Translator: Sam Najian \n" 7 | "Language-Team: Sam Najian \n" 8 | "Language: en_US\n" 9 | "MIME-Version: 1.0\n" 10 | "Content-Type: text/plain; charset=UTF-8\n" 11 | "Content-Transfer-Encoding: 8bit\n" 12 | "X-Generator: Poedit 1.6.9\n" 13 | "X-Poedit-Basepath: ..\n" 14 | "X-Poedit-SourceCharset: UTF-8\n" 15 | "X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;" 16 | "esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;" 17 | "_nx_noop:3c,1,2;__ngettext_noop:1,2\n" 18 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 19 | "X-Poedit-SearchPath-0: .\n" 20 | 21 | #: multi-domains-sso.php:237 22 | msgid "" 23 | "You have logged in successfully. You will be redirected to desired page " 24 | "during next 5 seconds." 25 | msgstr "" 26 | 27 | #: multi-domains-sso.php:353 28 | msgid "Incorrect or out of date login key" 29 | msgstr "" 30 | 31 | #: multi-domains-table.php:43 32 | msgid "Search" 33 | msgstr "" 34 | 35 | #: multi-domains-table.php:141 multi-domains-table.php:171 36 | msgid "unknown" 37 | msgstr "" 38 | 39 | #: multi-domains-table.php:147 40 | msgid "Edit" 41 | msgstr "" 42 | 43 | #: multi-domains-table.php:152 multi-domains.php:421 44 | msgid "Delete" 45 | msgstr "" 46 | 47 | #: multi-domains-table.php:184 48 | msgid "available" 49 | msgstr "" 50 | 51 | #: multi-domains-table.php:185 52 | msgid "unavailable" 53 | msgstr "" 54 | 55 | #: multi-domains-table.php:217 multi-domains.php:254 56 | msgid "Domain" 57 | msgstr "" 58 | 59 | #: multi-domains-table.php:218 60 | msgid "Visibility" 61 | msgstr "" 62 | 63 | #: multi-domains-table.php:222 64 | msgid "Wildcard DNS Availability" 65 | msgstr "" 66 | 67 | #: multi-domains.php:35 68 | msgid "The Multi-Domains plugin is only compatible with WordPress Multisite." 69 | msgstr "" 70 | 71 | #: multi-domains.php:238 72 | msgid "Multi-Domains" 73 | msgstr "" 74 | 75 | #: multi-domains.php:317 76 | #, php-format 77 | msgid "The domain %s is already in the list." 78 | msgstr "" 79 | 80 | #: multi-domains.php:343 multi-domains.php:387 81 | #, php-format 82 | msgid "The domain %s was not found in the list." 83 | msgstr "" 84 | 85 | #: multi-domains.php:413 86 | msgid "You do not have permission to access this page." 87 | msgstr "" 88 | 89 | #: multi-domains.php:430 90 | msgid "Error : the domain was not added" 91 | msgstr "" 92 | 93 | #: multi-domains.php:436 94 | msgid "Error : the domain was not saved" 95 | msgstr "" 96 | 97 | #: multi-domains.php:442 98 | msgid "Error : the domain was not deleted" 99 | msgstr "" 100 | 101 | #: multi-domains.php:448 102 | msgid "Error : the domains were not deleted" 103 | msgstr "" 104 | 105 | #: multi-domains.php:452 106 | msgid "Single Sign-on enabled." 107 | msgstr "" 108 | 109 | #: multi-domains.php:454 110 | msgid "Single Sign-on disabled." 111 | msgstr "" 112 | 113 | #: multi-domains.php:464 114 | msgid "Domains" 115 | msgstr "" 116 | 117 | #: multi-domains.php:471 118 | #, php-format 119 | msgid "" 120 | "Please copy the %1$s to %2$s/%1$s and uncomment the SUNRISE setting in the " 121 | "%2$s/%3$s file." 122 | msgstr "" 123 | 124 | #: multi-domains.php:477 125 | #, php-format 126 | msgid "" 127 | "Please copy the content of %1$s into %2$s/%1$s and uncomment the SUNRISE " 128 | "setting in the %2$s/%3$s file." 129 | msgstr "" 130 | 131 | #: multi-domains.php:485 132 | #, php-format 133 | msgid "Please uncomment the line %s in the %s file." 134 | msgstr "" 135 | 136 | #: multi-domains.php:495 137 | msgid "Search Added Domains" 138 | msgstr "" 139 | 140 | #: multi-domains.php:501 141 | msgid "" 142 | "In the DNS records for each domain added here, add a wildcard subdomain that " 143 | "points to this WordPress installation. It should look like:" 144 | msgstr "" 145 | 146 | #: multi-domains.php:503 147 | msgid "" 148 | "Pay attention that values of Wildcard DNS Availability column are refreshed " 149 | "each 5 minutes." 150 | msgstr "" 151 | 152 | #: multi-domains.php:505 153 | msgid "" 154 | "Change the DNS records for each domain to point to this WordPress " 155 | "installation." 156 | msgstr "" 157 | 158 | #: multi-domains.php:516 159 | msgid "Single Signon" 160 | msgstr "" 161 | 162 | #: multi-domains.php:518 163 | msgid "" 164 | "The Single Sign-on feature synchronize login cookies on all the domains." 165 | msgstr "" 166 | 167 | #: multi-domains.php:520 168 | msgid "Disable Single Sign-on" 169 | msgstr "" 170 | 171 | #: multi-domains.php:522 172 | msgid "Enable Single Sign-on" 173 | msgstr "" 174 | 175 | #: multi-domains.php:555 176 | #, php-format 177 | msgid "The domain %s has been successfully added." 178 | msgstr "" 179 | 180 | #: multi-domains.php:574 181 | #, php-format 182 | msgid "" 183 | "This feature allows you to set multiple domains that users can run their " 184 | "sites from, for example you can allow a user to run a site at %s and so on - " 185 | "all on this one Multisite install." 186 | msgstr "" 187 | 188 | #: multi-domains.php:578 multi-domains.php:608 189 | msgid "Add Domain" 190 | msgstr "" 191 | 192 | #: multi-domains.php:586 multi-domains.php:649 193 | msgid "Domain Name" 194 | msgstr "" 195 | 196 | #: multi-domains.php:587 multi-domains.php:651 197 | msgid "The domain name" 198 | msgstr "" 199 | 200 | #: multi-domains.php:590 multi-domains.php:656 201 | msgid "Domain Visibility" 202 | msgstr "" 203 | 204 | #: multi-domains.php:599 205 | msgid "Public: available to all users" 206 | msgstr "" 207 | 208 | #: multi-domains.php:600 209 | msgid "Restricted: available only to users which have special permission" 210 | msgstr "" 211 | 212 | #: multi-domains.php:601 213 | msgid "Private: available only to Super Admins" 214 | msgstr "" 215 | 216 | #: multi-domains.php:624 217 | #, php-format 218 | msgid "The domain %s has been successfully modified." 219 | msgstr "" 220 | 221 | #: multi-domains.php:643 222 | msgid "Edit Domain" 223 | msgstr "" 224 | 225 | #: multi-domains.php:671 226 | msgid "Save Domain" 227 | msgstr "" 228 | 229 | #: multi-domains.php:686 230 | #, php-format 231 | msgid "The domain %s has been successfully deleted." 232 | msgstr "" 233 | 234 | #: multi-domains.php:702 235 | msgid "The domains have been successfully deleted." 236 | msgstr "" 237 | 238 | #: multi-domains.php:797 239 | msgid "Your address will be" 240 | msgstr "" 241 | 242 | #: multi-domains.php:843 multi-domains.php:856 243 | msgid "Only the characters a-z and 0-9 recommended." 244 | msgstr "" 245 | -------------------------------------------------------------------------------- /multi-domains-sso.php: -------------------------------------------------------------------------------- 1 | _async = (int) get_site_option( 'multi_domains_single_signon_async', 0); 74 | 75 | $this->_add_filter( 'login_redirect', 'set_interim_login', 10, 3 ); 76 | $this->_add_filter( 'login_message', 'get_login_message' ); 77 | $this->_add_filter( 'login_url', 'update_login_url', 10, 2 ); 78 | $this->_add_action( 'login_init', 'reauthenticate_user', 10 ); 79 | $this->_add_action('wp_head', 'add_auth_script', 0 ); 80 | 81 | $this->_add_action( 'login_form_login', 'set_auth_script_for_login' ); 82 | $this->_add_action( 'login_footer', 'add_propagation_script' ); 83 | $this->_add_filter("logout_redirect", "logout_user_from_everywhere"); 84 | 85 | if( !$this->_async ){ 86 | $this->_add_action( 'plugins_loaded', 'authorize_user' ); 87 | } 88 | 89 | add_filter('init', array( $this, "add_query_var_for_endpoint" )); 90 | add_action('template_redirect', array( $this, 'dispatch_ajax_request' )); 91 | 92 | $this->_add_ajax_action( self::ACTION_PROPAGATE_USER, 'propagate_user', true, true ); 93 | } 94 | 95 | /** 96 | * Adds hook for login_head action if user tries to login. 97 | * 98 | * @since 4.1.2 99 | * @action login_form_login 100 | * 101 | * @access public 102 | */ 103 | public function set_auth_script_for_login() { 104 | $this->_add_action( 'login_head', 'add_auth_script', 0 ); 105 | } 106 | 107 | /** 108 | * Equalizes redirect_to domain name with login URL domain. 109 | * 110 | * @since 4.1.2.1 111 | * @filter login_url 10 2 112 | * 113 | * @param string $login_url The login URL. 114 | * @param string $redirect_to The redirect URL. 115 | * @return string Updated login URL. 116 | */ 117 | public function update_login_url( $login_url, $redirect_to ) { 118 | if( empty( $redirect_to ) ) 119 | return $login_url; 120 | 121 | $login_domain = parse_url( $login_url, PHP_URL_HOST ); 122 | $redirect_domain = parse_url( $redirect_to, PHP_URL_HOST ); 123 | if ( $login_domain != $redirect_domain ) { 124 | $redirect_to = str_replace( "://{$redirect_domain}", "://{$login_domain}", $redirect_to ); 125 | $login_url = esc_url_raw( add_query_arg( 'redirect_to', urlencode( $redirect_to ), $login_url ) ); 126 | } 127 | 128 | return $login_url; 129 | } 130 | 131 | /** 132 | * Logout user from all sites 133 | * 134 | * @since 4.4.1.0 135 | * 136 | * @access public 137 | */ 138 | public function logout_user_from_everywhere($redirect_to) { 139 | WP_User_Meta_Session_Tokens::drop_sessions(); 140 | return $redirect_to; 141 | } 142 | 143 | /** 144 | * Sets interim login mode. 145 | * 146 | * @since 4.1.2 147 | * @filter login_redirect 10 3 148 | * 149 | * @access public 150 | * @global boolean $interim_login Determines whether to show interim login page or not. 151 | * @param string $redirect_to The redirection URL. 152 | * @param string $requested_redirect_to The initial redirection URL. 153 | * @param WP_User|WP_Error $user The user or error object. 154 | * @return string The income redirection URL. 155 | */ 156 | public function set_interim_login( $redirect_to, $requested_redirect_to, $user ) { 157 | 158 | global $interim_login; 159 | if ( is_a( $user, 'WP_User' ) && get_current_blog_id() != 1 ) { 160 | if ( $this->is_mapped_domain() || $this->is_subdomain() ) { 161 | $interim_login = $this->_do_propagation = true; 162 | } 163 | } 164 | 165 | return $redirect_to; 166 | } 167 | 168 | /** 169 | * Updates login message for interim login page. 170 | * 171 | * @since 4.1.2 172 | * @filter login_message 173 | * 174 | * @access public 175 | * @param string $message The original message. 176 | * @return string The new extended login message. 177 | */ 178 | public function get_login_message( $message ) { 179 | return $this->_do_propagation 180 | ? '

' . esc_html__( 'You have logged in successfully. You will be redirected to desired page during next 5 seconds.', 'domainmap' ) . '

' 181 | : $message; 182 | } 183 | 184 | /** 185 | * Adds propagation scripts at interim login page after successfull login. 186 | * 187 | * @since 4.1.2 188 | * @access login_footer 189 | * 190 | * @access public 191 | * @global string $redirect_to The redirection URL. 192 | * @global WP_User $user Current user. 193 | */ 194 | public function add_propagation_script() { 195 | global $redirect_to, $user; 196 | 197 | 198 | if ( !$this->_do_propagation ) { 199 | return; 200 | } 201 | 202 | if ( ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' || $redirect_to == admin_url() ) ) { 203 | // If the user doesn't belong to a blog, send them to user admin. If the user can't edit posts, send them to their profile. 204 | if ( is_multisite() && !get_active_blog_for_user( $user->ID ) && !is_super_admin( $user->ID ) ) { 205 | $redirect_to = user_admin_url(); 206 | } elseif ( is_multisite() && !$user->has_cap( 'read' ) ) { 207 | $redirect_to = get_dashboard_url( $user->ID ); 208 | } elseif ( !$user->has_cap( 'edit_posts' ) ) { 209 | $redirect_to = admin_url( 'profile.php' ); 210 | } 211 | } 212 | ?> 213 | 217 | 218 | self::ACTION_PROPAGATE_USER, 222 | 'auth' => wp_generate_auth_cookie( $user->ID, time() + MINUTE_IN_SECONDS ), 223 | ), $this->get_main_ajax_url() ); 224 | 225 | $this->_add_script( $url ); 226 | } 227 | 228 | /** 229 | * Adds authorization script to the current page header. (Subsite) 230 | * 231 | * @since 4.1.2 232 | * @action wp_head 0 233 | * @action login_head 0 234 | * 235 | * @uses _add_auth_script_sync 236 | * @uses _add_auth_script_async 237 | * 238 | * @access public 239 | */ 240 | public function add_auth_script() { 241 | 242 | if ( is_user_logged_in() 243 | || 1 === get_current_blog_id() 244 | || filter_input( INPUT_GET, self::ACTION_KEY ) == self::ACTION_AUTHORIZE_USER 245 | || isset( $_POST["pwd"] ) 246 | ) return; 247 | 248 | if($this->_async) 249 | $this->_add_auth_script_async(); 250 | else 251 | $this->_add_auth_script_sync(); 252 | 253 | } 254 | 255 | private function _add_auth_script_sync(){ 256 | 257 | $url = add_query_arg( 'md_action', self::ACTION_SETUP_CDSSO, $this->_get_sso_endpoint_url() ); 258 | $this->_add_script( esc_url_raw( $url ) ); 259 | } 260 | 261 | private function _add_auth_script_async(){ 262 | 263 | $url = add_query_arg( array( 264 | 'md_action' => self::ACTION_CHECK_LOGIN_STATUS, 265 | 'domain' => $_SERVER['HTTP_HOST'] , 266 | ), $this->_get_sso_endpoint_url() 267 | ); 268 | 269 | $this->_add_iframe( esc_url_raw( $url ) ); 270 | } 271 | 272 | /** 273 | * Setups CDSSO for logged in user. (sync) 274 | * 275 | * @since 4.1.2 276 | * @action wp_ajax_domainmap-setup-cdsso 277 | * @action wp_ajax_nopriv_domainmap-setup-cdsso 278 | * 279 | * @access public 280 | */ 281 | public function setup_cdsso() { 282 | header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) ); 283 | if ( !is_user_logged_in() || empty( $_SERVER['HTTP_REFERER'] ) ) { 284 | header( "Vary: Accept-Encoding" ); // Handle proxies 285 | header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + ( 2 * MINUTE_IN_SECONDS ) ) . " GMT" ); 286 | exit; 287 | } 288 | 289 | $url = add_query_arg( array( 290 | self::ACTION_KEY => self::ACTION_AUTHORIZE_USER, 291 | 'auth' => wp_generate_auth_cookie( get_current_user_id(), time() + ( 2 * MINUTE_IN_SECONDS ) ), 292 | ), $_SERVER['HTTP_REFERER'] ); 293 | ?> 294 | window.location.replace(""); 295 | 310 | 311 | _flush_rewrite_rules(); 327 | return $vars; 328 | } 329 | 330 | /** 331 | * Flushes rewrite rules if needed 332 | * 333 | * @since 4.3.1 334 | */ 335 | function _flush_rewrite_rules(){ 336 | $key = multi_domain::FLUSHED_REWRITE_RULES . get_current_blog_id(); 337 | if( !get_site_option( $key ) ){ 338 | flush_rewrite_rules(); 339 | update_site_option( $key , true); 340 | } 341 | } 342 | 343 | /** 344 | * Returns relevant endpoint url 345 | * 346 | * @since 4.3.1 347 | * @param bool $subsite 348 | * @param null $domain 349 | * 350 | * @return string 351 | */ 352 | private function _get_sso_endpoint_url( $subsite = false, $domain = null){ 353 | global $wp_rewrite, $current_blog, $current_site;; 354 | 355 | $admin_scheme = is_ssl() ? "https://" : "http://"; 356 | 357 | if( $subsite ){ 358 | $domain = is_null( $domain ) ? $current_blog->domain : $domain; 359 | $url = $admin_scheme . $domain . "/"; 360 | }else{ 361 | $url = trailingslashit( network_home_url("/", $admin_scheme) ); 362 | } 363 | 364 | return $wp_rewrite->using_permalinks() ? $url . self::SSO_ENDPOINT . "/" . time() . "/" : $url . "?" . self::SSO_ENDPOINT . "=" . time() ; 365 | } 366 | 367 | 368 | /** 369 | * Dispatches ajax request to the relevant methods 370 | * 371 | * @since 4.3.1 372 | */ 373 | function dispatch_ajax_request(){ 374 | 375 | global $wp_query; 376 | 377 | if( !isset( $wp_query->query_vars[ self::SSO_ENDPOINT ] ) ) return; 378 | 379 | define('DOING_AJAX', true); 380 | header('Content-Type: text/html'); 381 | send_nosniff_header(); 382 | header('Cache-Control: no-cache'); 383 | header('Pragma: no-cache'); 384 | 385 | if( isset( $_REQUEST["md_action"] ) ){ 386 | $action = $_REQUEST["md_action"]; 387 | }elseif( isset( $_REQUEST["q"] ) ){ 388 | $q = $_REQUEST["q"]; 389 | $parsed = parse_url($q ); 390 | 391 | if( isset( $parsed['query'] ) && strpos($parsed['query'], "md_action") !== false ){ // if query is set 392 | $action = str_replace("md_action=", "", $parsed['query']); 393 | }else{ 394 | $prefix = "?md_action="; 395 | $pos = strpos( $q, $prefix ); 396 | $action = substr($q, $pos + strlen($prefix)); 397 | } 398 | 399 | } 400 | 401 | if( !empty( $action ) ){ 402 | $method = str_replace(array("multidomain-", "-"), array("", "_"), $action); 403 | 404 | if( method_exists("Multidomains_Sso", $method) ) 405 | call_user_func(array($this, $method)); 406 | else 407 | wp_send_json_error( "Method " . $method . " not found" ); 408 | } 409 | exit; 410 | } 411 | 412 | /** 413 | * Checks login status of the user on the main site 414 | * 415 | * @uses authorize_user_async 416 | * @since 4.3.1 417 | */ 418 | function check_login_status(){ 419 | 420 | header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) ); 421 | if ( !is_user_logged_in() ) { 422 | header( "Vary: Accept-Encoding" ); // Handle proxies 423 | header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + MINUTE_IN_SECONDS ) . " GMT" ); 424 | exit; 425 | } 426 | 427 | $domain_name = filter_input( INPUT_GET, 'domain' ); 428 | 429 | ?> 430 | // Starting Domain Mapping SSO 431 | self::ACTION_AUTHORIZE_USER_ASYNC, 434 | 'auth' => wp_generate_auth_cookie( get_current_user_id(), time() + MINUTE_IN_SECONDS ), 435 | 'refresh' => 1 436 | ); 437 | 438 | $url = add_query_arg( $args, $this->_get_sso_endpoint_url( true, $domain_name ) ); 439 | 440 | $url = set_url_scheme( $url, "http" ); 441 | $this->_add_inner_iframe( esc_url_raw( $url ) ); 442 | 443 | } 444 | 445 | /** 446 | * Adds iframe 447 | * 448 | * 449 | * @since 4.4.0 450 | * @param $url 451 | */ 452 | private function _add_iframe( $url ){ 453 | ?> 454 | 473 | 484 | (function(window) { 485 | var document = window.top.document; 486 | var url = ''; 487 | var iframe = document.createElement('iframe'); 488 | (iframe.frameElement || iframe).style.cssText = 489 | "width: 0; height: 0; border: 0"; 490 | iframe.src = "javascript:false"; 491 | var where = document.getElementsByTagName('script')[0]; 492 | where.parentNode.insertBefore(iframe, where); 493 | var doc = iframe.contentWindow.document; 494 | doc.open().write(''); 498 | doc.close(); 499 | 500 | }(parent.top.window)); 501 | false, 'auth' => false ) ); 519 | 520 | wp_redirect( esc_url_raw( $redirect_to ) ); 521 | exit; 522 | } else { 523 | wp_die( __( "Incorrect or out of date login key", 'domainmap' ) ); 524 | } 525 | } 526 | } 527 | 528 | /** 529 | * Sets auth cookie for the user on the subsite ( async ) 530 | * 531 | * @since 4.3.1 532 | */ 533 | private function authorize_user_async(){ 534 | header( "Content-Type: text/javascript; charset=" . get_bloginfo( 'charset' ) ); 535 | 536 | $user_id = wp_validate_auth_cookie( filter_input( INPUT_GET, 'auth' ), 'auth' ); 537 | $refresh = filter_input( INPUT_GET, 'refresh' ); 538 | 539 | if ( $user_id ) { 540 | wp_set_auth_cookie( $user_id ); 541 | if( $refresh ){ 542 | ?> 543 | window.top.location.reload(); 544 | ID ) && !isset( $_REQUEST['loggedout'] ) && !isset( $_REQUEST['action'] ) ){ 586 | 587 | 588 | if( !isset( $redirect_to ) ) 589 | $redirect_to = $this->_get_reauthenticate_redirect_to(); 590 | 591 | wp_set_auth_cookie( $current_user->ID ); 592 | wp_redirect( $redirect_to ); 593 | exit(); 594 | } 595 | } 596 | 597 | /** 598 | * Returns $redirect_to variable on reauthentication 599 | * 600 | * 601 | * @since 4.4.0.7 602 | * @return mixed|string|void 603 | */ 604 | private function _get_reauthenticate_redirect_to(){ 605 | $secure_cookie = false; 606 | // If the user wants ssl but the session is not ssl, force a secure cookie. 607 | if ( !empty($_POST['log']) && !force_ssl_admin() ) { 608 | $user_name = sanitize_user($_POST['log']); 609 | if ( $user = get_user_by('login', $user_name) ) { 610 | if ( get_user_option('use_ssl', $user->ID) ) { 611 | $secure_cookie = true; 612 | force_ssl_admin(true); 613 | } 614 | } 615 | } 616 | 617 | if ( isset( $_REQUEST['redirect_to'] ) ) { 618 | $redirect_to = $_REQUEST['redirect_to']; 619 | // Redirect to https if user wants ssl 620 | if ( $secure_cookie && false !== strpos($redirect_to, 'wp-admin') ) 621 | $redirect_to = preg_replace('|^http://|', 'https://', $redirect_to); 622 | } else { 623 | $redirect_to = admin_url(); 624 | } 625 | 626 | return $redirect_to; 627 | } 628 | 629 | } 630 | endif; -------------------------------------------------------------------------------- /multi-domains-table.php: -------------------------------------------------------------------------------- 1 | __( 'Search' ), 44 | 'single' => 'domain', 45 | 'plural' => 'domains', 46 | 'ajax' => false, 47 | 'autoescape' => true, 48 | ), $args ) ); 49 | } 50 | 51 | /** 52 | * Displays table navigation section. 53 | * 54 | * @since 1.3.1 55 | * 56 | * @access public 57 | * @param string $which The section where table navigation will be displayed. 58 | */ 59 | public function display_tablenav( $which ) { 60 | echo '
'; 61 | echo '
'; 62 | $this->bulk_actions( $which ); 63 | echo '
'; 64 | $this->extra_tablenav( $which ); 65 | $this->pagination( $which ); 66 | echo '
'; 67 | echo '
'; 68 | } 69 | 70 | /** 71 | * Returns checkbox column value. 72 | * 73 | * @since 1.3.1 74 | * 75 | * @access public 76 | * @param array $item The table row to display. 77 | * @return string The value to display. 78 | */ 79 | public function column_cb( $item ) { 80 | return sprintf( '', $this->_args['plural'], $item['domain_name'] ); 81 | } 82 | 83 | /** 84 | * Displays the search box if it was enabled in table arguments. 85 | * 86 | * @since 1.3.1 87 | * 88 | * @access public 89 | * @param string $text The search button text. 90 | * @param string $input_id The search input id. 91 | */ 92 | public function search_box( $text, $input_id ) { 93 | if ( isset( $this->_args['search_box'] ) && $this->_args['search_box'] ) { 94 | parent::search_box( $text, $input_id ); 95 | } 96 | } 97 | 98 | /** 99 | * Auto escapes all values and displays the table. 100 | * 101 | * @since 1.3.1 102 | * 103 | * @access public 104 | */ 105 | public function display() { 106 | if ( is_array( $this->items ) && $this->_args['autoescape'] ) { 107 | foreach ( $this->items as &$item ) { 108 | foreach ( $item as &$value ) { 109 | $value = esc_html( $value ); 110 | } 111 | } 112 | } 113 | 114 | parent::display(); 115 | } 116 | 117 | /** 118 | * Returns associative array with the list of bulk actions available on this table. 119 | * 120 | * @since 1.3.1 121 | * 122 | * @access protected 123 | * @return array The associative array of bulk actions. 124 | */ 125 | public function get_bulk_actions() { 126 | return isset( $this->_args['actions'] ) 127 | ? $this->_args['actions'] 128 | : array(); 129 | } 130 | 131 | /** 132 | * Returns the domain name. 133 | * 134 | * @since 1.3.1 135 | * 136 | * @access public 137 | * @param array $item Array of domain data. 138 | * @return string Domain name. 139 | */ 140 | public function column_domain( $item ) { 141 | $title = !empty( $item['domain_name'] ) ? $item['domain_name'] : esc_html__( 'unknown', 'multi_domain' ); 142 | 143 | $actions = array( 144 | 'edit' => sprintf( 145 | '%s', 146 | esc_url( add_query_arg( array( 'edit' => '1', 'name' => $item['domain_name'] ) ) ), 147 | __( 'Edit', 'multi_domain' ) 148 | ), 149 | 'delete' => sprintf( 150 | '%s', 151 | esc_url( add_query_arg( array( 'delete' => '1', 'name' => $item['domain_name'] ) ) ), 152 | __( 'Delete', 'multi_domain' ) 153 | ), 154 | ); 155 | 156 | return sprintf( '%s %s', '#', $title, $this->row_actions( $actions ) ); 157 | } 158 | 159 | /** 160 | * Returns domain visibility. 161 | * 162 | * @since 1.3.1 163 | * 164 | * @access public 165 | * @param array $item Array of domain data. 166 | * @return string Domain visibility. 167 | */ 168 | public function column_visibility( $item ) { 169 | return !empty( $item['domain_status'] ) 170 | ? $item['domain_status'] 171 | : esc_html__( 'unknown', 'multi_domain' ); 172 | } 173 | 174 | /** 175 | * Returns wildcard DNS availability status. 176 | * 177 | * @since 1.3.1 178 | * 179 | * @access public 180 | * @param array $item Array of domain data. 181 | * @return string Wildcard DNS availability status. 182 | */ 183 | public function column_availability( $item ) { 184 | $true = '' . __( 'available', 'multi_domain' ) . ''; 185 | $false = '' . __( 'unavailable', 'multi_domain' ) . ''; 186 | 187 | if ( $item['domain_name'] == DOMAIN_CURRENT_SITE ) { 188 | return $true; 189 | } 190 | 191 | $transient = 'multi_domain_availability-' . $item['domain_name']; 192 | $available = get_site_transient( $transient ); 193 | if ( $available == false ) { 194 | $response = wp_remote_get( 'http://' . substr( md5( time() ), 0, 6 ) . '.' . $item['domain_name'], array( 195 | 'timeout' => 5, 196 | 'httpversion' => '1.1', 197 | ) ); 198 | 199 | $available = !is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) == 200; 200 | set_site_transient( $transient, $available ? 1 : 0, 5 * MINUTE_IN_SECONDS ); 201 | } 202 | 203 | return $available ? $true : $false; 204 | } 205 | 206 | /** 207 | * Returns tabel columns. 208 | * 209 | * @since 1.3.1 210 | * 211 | * @access public 212 | * @return array The array of table columns to display. 213 | */ 214 | public function get_columns() { 215 | $columns = array( 216 | 'cb' => '', 217 | 'domain' => __( 'Domain', 'multi_domain' ), 218 | 'visibility' => __( 'Visibility', 'multi_domain' ), 219 | ); 220 | 221 | if ( is_subdomain_install() ) { 222 | $columns['availability'] = __( 'Wildcard DNS Availability', 'multi_domain' ); 223 | } 224 | 225 | return $columns; 226 | } 227 | 228 | /** 229 | * Fetches domains from database. 230 | * 231 | * @since 1.3.1 232 | * 233 | * @access public 234 | */ 235 | public function prepare_items() { 236 | $this->_column_headers = array( 237 | $this->get_columns(), 238 | array(), 239 | $this->get_sortable_columns() 240 | ); 241 | 242 | $per_page = 10; 243 | $offset = ( $this->get_pagenum() - 1 ) * $per_page; 244 | 245 | $items = get_site_option( 'md_domains' ); 246 | $primary = wp_list_filter( $items, array( 'domain_name' => DOMAIN_CURRENT_SITE ) ); 247 | $else = wp_list_filter( $items, array( 'domain_name' => DOMAIN_CURRENT_SITE ), 'NOT' ); 248 | 249 | $items = array_merge( $primary, $else ); 250 | 251 | $search = isset( $_REQUEST['s'] ) ? trim( $_REQUEST['s'] ) : ''; 252 | if ( !empty( $search ) ) { 253 | $tmp = array(); 254 | foreach ( $items as $item ) { 255 | if ( stripos( $item['domain_name'], $search ) !== false ) { 256 | $tmp[] = $item; 257 | } 258 | } 259 | $items = $tmp; 260 | } 261 | 262 | $this->items = array_slice( $items, $offset, $per_page );; 263 | 264 | $total_items = count( $items ); 265 | $this->set_pagination_args( array( 266 | 'total_items' => $total_items, 267 | 'per_page' => $per_page, 268 | 'total_pages' => ceil( $total_items / $per_page ) 269 | ) ); 270 | } 271 | 272 | } 273 | -------------------------------------------------------------------------------- /multi-domains.php: -------------------------------------------------------------------------------- 1 | db = $wpdb; 95 | $this->upgrade_sunrise(); 96 | 97 | // Set plugin default options if the plugin was not installed before 98 | add_action( 'init', array( $this, 'activate_plugin' ) ); 99 | // Enable or disable single signon 100 | add_action( 'init', array( $this, 'switch_single_signon' ) ); 101 | // Run plugin functions 102 | add_action( 'init', array( $this, 'setup_plugin' ) ); 103 | // Add in the cross domain logins 104 | add_action( 'init', array( $this, 'build_stylesheet_for_cookie' ) ); 105 | 106 | $skip_site_search = defined( 'MD_SKIP_SITE_SEARCH_QUERY_REWRITE' ) && MD_SKIP_SITE_SEARCH_QUERY_REWRITE; 107 | if ( is_network_admin() && is_subdomain_install() && !$skip_site_search ) { 108 | add_filter( 'query', array( $this, 'subdomain_filter_site_search_query' ) ); 109 | } 110 | 111 | 112 | /** 113 | * Handle cross domain single sign on if domain mapping's single signon is not active 114 | */ 115 | $mapping_options = get_site_option("domain_mapping"); 116 | if ( get_site_option( 'multi_domains_single_signon' ) === 'enabled' && ( !class_exists("Domainmap_Module_Cdsso") || ( class_exists("Domainmap_Module_Cdsso") && false === $mapping_options['map_crossautologin'] ) ) ) { 117 | new Multidomains_Sso(); 118 | } 119 | } 120 | 121 | function subdomain_filter_site_search_query( $query ) { 122 | // WP 3.3+ scoping 123 | if ( function_exists( 'get_current_screen' ) ) { 124 | $screen = get_current_screen(); 125 | if ( !$screen || 'sites-network' != $screen->id ) { 126 | return $query; // Not a proper page 127 | } 128 | } 129 | 130 | global $current_site, $s; 131 | if ( !preg_match( '/' . preg_quote( $this->db->blogs . '.domain', '/' ) . '/', $query ) ) { 132 | return $query; 133 | } 134 | 135 | $replacement = preg_match( '/\./', $s ) ? '\1%' : '\1.%'; // Rewrite scoping for full sub+domain searches 136 | $query = preg_replace( '/(\b|%)' . preg_quote( ".{$current_site->domain}", '/' ) . '\b/', $replacement, $query ); 137 | 138 | return $query; 139 | } 140 | 141 | /** 142 | * Run on plugin activation. 143 | */ 144 | function activate_plugin() { 145 | $version = get_site_option( 'md_version' ); 146 | if ( empty( $version ) ) { 147 | $domains = array( 148 | array( 149 | 'domain_name' => DOMAIN_CURRENT_SITE . PATH_CURRENT_SITE, 150 | 'domain_status' => 'public' 151 | ) 152 | ); 153 | 154 | update_site_option( 'md_domains', apply_filters( 'md_default_domains', $domains ) ); 155 | update_site_option( 'md_version', $this->version ); 156 | } 157 | 158 | if ( version_compare( $this->version, $version, '>' ) ) { 159 | update_site_option( 'md_version', $this->version ); 160 | } 161 | } 162 | 163 | /** 164 | * Run plugin functions. 165 | */ 166 | function setup_plugin() { 167 | $this->domains = get_site_option( 'md_domains' ); 168 | 169 | // handle translations 170 | load_plugin_textdomain( $this->textdomain, false, dirname( plugin_basename( __FILE__ ) ) . '/languages' ); 171 | 172 | // Add the super admin page 173 | add_action( 'network_admin_menu', array( $this, 'network_admin_page' ) ); 174 | 175 | // Enqueue javascript 176 | $this->enqueue_jquery(); 177 | add_action( 'wp_head', array( $this, 'enqueue_signup_javascript' ) ); 178 | 179 | // Empty $current_site global on signup page 180 | add_action( 'signup_hidden_fields', array( $this, 'modify_current_site' ) ); 181 | // Populate $current_site, $domain and $base globals on signup page with values choosen by the user on signup page 182 | add_filter( 'newblogname', array( $this, 'set_registration_globals' ) ); 183 | add_action( 'admin_action_add-site', array( $this, 'set_registration_globals' ) ); // For when the site is created from network admin 184 | add_filter( 'add_signup_meta', array( $this, 'set_other_registration_globals' ) ); 185 | // Restore default $current_site global on signup page 186 | add_action( 'signup_finished', array( $this, 'restore_current_site' ) ); 187 | add_action( 'wpmu_new_blog', array( $this, 'restore_current_site' ) ); 188 | 189 | // Populate $current_site on admin edit page 190 | add_action( 'wpmuadminedit', array( $this, 'wpmuadminedit' ) ); 191 | 192 | // Extends blog registration forms 193 | add_action( 'signup_blogform', array( $this, 'extend_signup_blogform' ) ); // default and buddypress blog creation forms 194 | add_action( 'bp_signup_blog_url_errors', array( $this, 'extend_signup_blogform' ) ); // buddypress signup form 195 | add_action( 'admin_footer', array( $this, 'extend_admin_blogform' ) ); // admin site creation form 196 | 197 | // modify blog columns on Super Admin > Sites page 198 | add_filter( 'wpmu_blogs_columns', array( $this, 'blogs_columns' ) ); 199 | add_action( 'manage_blogs_custom_column', array( $this, 'manage_blogs_custom_column' ), 10, 2 ); 200 | 201 | // Canonicalize main URL 202 | if ( defined( 'MD_CANONICAL_DOMAIN' ) && MD_CANONICAL_DOMAIN ) { 203 | // Removing default canonical action - note: custom SEO in themes 204 | /// or plugins will override this behavior. 205 | remove_action( 'wp_head', 'rel_canonical' ); 206 | add_action( 'wp_head', array( $this, 'canonicalize_main_domain' ) ); 207 | } 208 | } 209 | 210 | function canonicalize_main_domain() { 211 | global $wp; 212 | 213 | if ( !defined( 'MD_CANONICAL_DOMAIN' ) || !MD_CANONICAL_DOMAIN ) { 214 | return false; // Nothing to do 215 | } 216 | 217 | $link = site_url( $wp->request ); 218 | foreach ( $this->domains as $data ) { 219 | if ( preg_match( '/' . preg_quote( $data['domain_name'], '/' ) . '/i', $link ) ) { 220 | $link = preg_replace( '/' . preg_quote( $data['domain_name'], '/' ) . '/i', MD_CANONICAL_DOMAIN, $link ); 221 | break; 222 | } 223 | } 224 | 225 | $link = apply_filters( 'md-canonical_domain-replacement_link', $link ); 226 | if ( !$link ) { 227 | return false; 228 | } 229 | 230 | printf( '', esc_url( $link ) ); 231 | } 232 | 233 | /** 234 | * Add network admin page 235 | */ 236 | function network_admin_page() { 237 | global $wpmudev_notices; 238 | 239 | $title = __( 'Multi-Domains', $this->textdomain ); 240 | $page = add_submenu_page( 'settings.php', $title, $title, 'manage_network', 'multi-domains', array( $this, 'management_page' ) ); 241 | 242 | $wpmudev_notices[] = array( 243 | 'id' => 154, 244 | 'name' => 'Multi-Domains for Multisite', 245 | 'screens' => array( "{$page}-network" ), 246 | ); 247 | } 248 | 249 | /** 250 | * Add domain colum to Super Admin > Sites table. 251 | */ 252 | function blogs_columns( $sites_columns ) { 253 | 254 | if( !is_subdomain_install() ) 255 | $sites_columns['domain'] = __( 'Domain', $this->textdomain ); 256 | 257 | return $sites_columns; 258 | 259 | } 260 | 261 | /** 262 | * Add domain column to Super Admin > Sites table. 263 | */ 264 | function manage_blogs_custom_column( $column_name, $blog_id ) { 265 | if ( !is_subdomain_install() ) { 266 | $bloginfo = get_blog_details( (int) $blog_id, false ); 267 | echo $bloginfo->domain; 268 | } 269 | } 270 | 271 | /** 272 | * Update domains in the database. 273 | */ 274 | function update_domains_option() { 275 | return update_site_option( 'md_domains', apply_filters( 'md_update_domains_option', $this->domains_sort() ) ); 276 | } 277 | 278 | /** 279 | * Sort domains bidimensional array by domain name. 280 | */ 281 | function domains_sort( $orderby = 'domain_name' ) { 282 | $sort_array = array(); 283 | $domains = $this->domains; 284 | 285 | foreach( $domains as $domain ) { 286 | foreach( $domain as $key => $value ) { 287 | if( !isset( $sort_array[$key] ) ) 288 | $sort_array[$key] = array(); 289 | 290 | $sort_array[$key][] = $value; 291 | } 292 | } 293 | 294 | array_multisort( $sort_array[$orderby], SORT_ASC, $domains ); 295 | 296 | return $this->domains = $domains; 297 | } 298 | 299 | /** 300 | * Add domain to the list. 301 | */ 302 | function add_domain( $domain = array() ) { 303 | 304 | $domains = $this->domains; 305 | 306 | for( $i = 0; $i < count( $domains ); $i++ ) { 307 | if( $domains[$i]['domain_name'] == $domain['domain_name'] ) { 308 | $domain_exists = 1; 309 | break; 310 | } 311 | } 312 | 313 | if( empty( $domain_exists ) ) { 314 | $domains[] = apply_filters( 'md_add_domain', $domain ); 315 | $this->domains = $domains; 316 | return true; 317 | } else { 318 | return new WP_Error( 'md_domain_exists', sprintf( __( "The domain %s is already in the list.", $this->textdomain ), $domain['domain_name'] ) ); 319 | } 320 | 321 | } 322 | 323 | /** 324 | * Modify domain details. 325 | */ 326 | function update_domain( $domain = array() ) { 327 | 328 | $domains = $this->domains; 329 | 330 | for( $i = 0; $i < count( $domains ); $i++ ) { 331 | if( $domains[$i]['domain_name'] == $domain['domain_name'] ) { 332 | $current_domain = $domains[$i]; 333 | $current_domain['domain_status'] = $domain['domain_status']; 334 | $domains[$i] = apply_filters( 'md_update_domain', $current_domain, $domain ); 335 | $domain_exists = 1; 336 | break; 337 | } 338 | } 339 | 340 | if( !empty( $domain_exists ) ) { 341 | $this->domains = $domains; 342 | return true; 343 | } else { 344 | return new WP_Error( 'md_domain_not_found', sprintf( __( "The domain %s was not found in the list.", $this->textdomain ), $domain['domain_name'] ) ); 345 | } 346 | 347 | } 348 | 349 | /** 350 | * Get domain attributes. 351 | */ 352 | function get_domain( $name_or_id ) { 353 | $domains = $this->domains; 354 | 355 | if( is_numeric( $name_or_id ) ) { 356 | return isset( $domains[$name_or_id] ) ? $domains[$name_or_id] : false; 357 | } else { 358 | foreach( $domains as $domain ) { 359 | if( $domain['domain_name'] == $name_or_id ) 360 | return $domain; 361 | } 362 | } 363 | 364 | return false; 365 | } 366 | 367 | /** 368 | * Remove one domain from the list. 369 | */ 370 | function delete_domain( $domain_name = '' ) { 371 | 372 | if( !empty( $domain_name ) ) { 373 | 374 | $domains = $this->domains; 375 | 376 | for( $i = 0; $i < count( $domains ); $i++ ) { 377 | if( $domains[$i]['domain_name'] == $domain_name ) { 378 | unset( $domains[$i] ); 379 | $domain_exists = 1; 380 | break; 381 | } 382 | } 383 | 384 | if( isset( $domain_exists ) ) { 385 | $this->domains = apply_filters( 'md_delete_domain', array_values( $domains ) ); 386 | return true; 387 | } else { 388 | return new WP_Error( 'md_domain_not_found', sprintf( __( "The domain %s was not found in the list.", $this->textdomain ), $domain_name ) ); 389 | } 390 | 391 | } 392 | 393 | } 394 | 395 | /** 396 | * Return Domains status list 397 | */ 398 | function domain_status() { 399 | 400 | if( $this->show_restricted_domains() == true ) { 401 | $status = array( 'public', 'restricted', 'private' ); 402 | } else { 403 | $status = array( 'public', 'private' ); 404 | } 405 | return apply_filters( 'md_domain_status', $status ); 406 | 407 | } 408 | 409 | /** 410 | * Super Admin page. 411 | */ 412 | function management_page() { 413 | if ( !is_super_admin() ) { 414 | wp_die( '

' . __( 'You do not have permission to access this page.', $this->textdomain ) . '

' ); 415 | } 416 | 417 | require_once dirname( __FILE__ ) . '/multi-domains-table.php'; 418 | 419 | $table = new Multidomains_Table( array( 420 | 'search_box' => true, 421 | 'actions' => array( 422 | 'deletedomains' => __( 'Delete', $this->textdomain ) 423 | ), 424 | ) ); 425 | 426 | $messages = array(); 427 | if ( isset( $_POST['add_domain'] ) && isset( $_POST['domain_name'] ) && isset( $_POST['domain_status'] ) ) { 428 | if ( ( $message = $this->add_domain_post() ) ) { 429 | $messages[] = '

' . $message . '

'; 430 | } else { 431 | $messages[] = '

' . __( 'Error : the domain was not added', $this->textdomain ) . '

'; 432 | } 433 | } elseif ( isset( $_POST['edit_domain'] ) && isset( $_POST['domain_name'] ) && isset( $_POST['domain_status'] ) ) { 434 | if ( ( $message = $this->edit_domain_post() ) ) { 435 | $messages[] = '

' . $message . '

'; 436 | } else { 437 | $messages[] = '

' . __( 'Error : the domain was not saved', $this->textdomain ) . '

'; 438 | } 439 | } elseif ( isset( $_GET['delete'] ) && isset( $_GET['name'] ) ) { 440 | if ( ( $message = $this->delete_domain_post() ) ) { 441 | $messages[] = '

' . $message . '

'; 442 | } else { 443 | $messages[] = '

' . __( 'Error : the domain was not deleted', $this->textdomain ) . '

'; 444 | } 445 | } elseif ( $table->current_action() == 'deletedomains' ) { 446 | if ( ( $message = $this->delete_domains_post() ) ) { 447 | $messages[] = '

' . $message . '

'; 448 | } else { 449 | $messages[] = '

' . __( 'Error : the domains were not deleted', $this->textdomain ) . '

'; 450 | } 451 | } elseif ( !empty( $_GET['single_signon'] ) ) { 452 | if ( 'enable' == $_GET['single_signon'] ) { 453 | $_message = $_GET['async'] === "true" ? __( 'Async Single Sign-on enabled.', $this->textdomain ) : __( 'Sync Single Sign-on enabled.', $this->textdomain ); 454 | $messages[] = '

' . $_message . '

'; 455 | } elseif ( 'disable' == $_GET['single_signon'] ) { 456 | $messages[] = '

' . __( 'Single Sign-on disabled.', $this->textdomain ) . '

'; 457 | } 458 | } 459 | 460 | $exists = is_readable( WP_CONTENT_DIR . '/sunrise.php' ); 461 | $valid = defined( 'MULTIDOMAINS_SUNRISE_VERSION' ) && version_compare( MULTIDOMAINS_SUNRISE_VERSION, $this->sunrise, '=' ); 462 | 463 | ?>
464 | 465 |
466 |

textdomain ) ?>

467 | 468 | 469 | 470 | 471 |
472 |

textdomain ), 'sunrise.php', WP_CONTENT_DIR, 'wp-config.php' ) 474 | ?>

475 |
476 | 477 |
478 |

textdomain ), 'sunrise.php', WP_CONTENT_DIR, 'wp-config.php' ) 480 | ?>

481 |
482 | 483 | 484 | 485 |
486 |

textdomain ), "//define( 'SUNRISE', 'on' );", ABSPATH . 'wp-config.php' ) 488 | ?>

489 |
490 | 491 | 492 |
493 |
494 | 495 |
496 | prepare_items() ?> 497 | search_box( __( 'Search Added Domains', $this->textdomain ), 'multi_domains_search' ) ?> 498 | display() ?> 499 |
500 | 501 |

textdomain ); 504 | echo ' A *.domain.com
'; 505 | _e( 'Pay attention that values of Wildcard DNS Availability column are refreshed each 5 minutes.', $this->textdomain ); 506 | else: 507 | _e( 'Change the DNS records for each domain to point to this WordPress installation.', $this->textdomain ); 508 | endif; 509 | ?>

510 |
511 | 512 |
513 | 514 | edit_domain_form() ?> 515 | 516 | add_domain_form() ?> 517 | 518 |

textdomain ) ?>

519 | 520 |

textdomain ) ?>

521 | textdomain ) : __( 'Disable Sync Single Sign-on', $this->textdomain ); 523 | ?> 524 |

525 | 526 |

527 | textdomain ) ?> 528 |

529 |

530 | textdomain ) ?> 531 |

532 | 533 | 534 |
535 |
536 |
add_domain( $_POST ); 564 | if ( is_wp_error( $result ) ) { 565 | return $result->get_error_message(); 566 | } else { 567 | $this->update_domains_option(); 568 | return sprintf( __( 'The domain %s has been successfully added.', $this->textdomain ), $_POST['domain_name'] ); 569 | } 570 | } 571 | } 572 | 573 | /** 574 | * Domain addition form. 575 | */ 576 | function add_domain_form() { 577 | $sites_format = is_subdomain_install() 578 | ? 'blogname.domain1.com, blogname.domain2.com' 579 | : 'domain1.com/blogname, domain2.com/blogname'; 580 | 581 | $submit_url = esc_url( add_query_arg( array( 582 | 'edit' => false, 583 | 'name' => false, 584 | ) ) ); 585 | 586 | $description = sprintf( 587 | __( 'This feature allows you to set multiple domains that users can run their sites from, for example you can allow a user to run a site at %s and so on - all on this one Multisite install.', $this->textdomain ), 588 | $sites_format 589 | ); 590 | 591 | ?>

textdomain ) ?>

592 | 593 |

594 | 595 |
596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 616 | 617 | 618 | 619 |
http:// (e.g.: domain.com)
605 |
612 | textdomain ) ?>
613 | show_restricted_domains() == true ) echo __( 'Restricted: available only to users which have special permission', $this->textdomain ) . '
'; ?> 614 | textdomain ) ?>
615 |
620 |

621 | 622 |

623 |
624 | update_domain( $_POST ); 633 | if ( is_wp_error( $result ) ) { 634 | return $result->get_error_message(); 635 | } else { 636 | $this->update_domains_option(); 637 | return sprintf( __( "The domain %s has been successfully modified.", $this->textdomain ), $_POST['domain_name'] ); 638 | } 639 | } 640 | } 641 | 642 | /** 643 | * Domain edition form. 644 | */ 645 | function edit_domain_form() { 646 | if( !isset( $_GET['name'] ) ) { 647 | return; 648 | } 649 | 650 | $domain = $this->get_domain( $_GET['name'] ); 651 | $submit_url = esc_url( add_query_arg( array( 652 | 'edit' => false, 653 | 'name' => false, 654 | ) ) ); 655 | 656 | ?>

textdomain ) ?>

657 | 658 |
659 | 660 | 661 | 662 | 663 | 667 | 668 | 669 | 670 | 679 | 680 | 681 | 682 |
664 | http:// 665 | 666 |
671 | 678 |
683 |

684 | 685 |

686 |
delete_domain( $_GET['name'] ); 695 | if ( is_wp_error( $result ) ) { 696 | return $result->get_error_message(); 697 | } else { 698 | $this->update_domains_option(); 699 | return sprintf( __( "The domain %s has been successfully deleted.", $this->textdomain ), $_GET['name'] ); 700 | } 701 | } 702 | } 703 | 704 | /** 705 | * Process multiple domains deletion form data. 706 | */ 707 | function delete_domains_post() { 708 | if ( filter_input( INPUT_POST, 'action' ) == 'deletedomains' || filter_input( INPUT_POST, 'action2' ) == 'deletedomains' ) { 709 | $domains = $_POST['domains']; 710 | if ( !empty( $domains ) ) { 711 | foreach ( $domains as $domain ) { 712 | $this->delete_domain( $domain ); 713 | } 714 | $this->update_domains_option(); 715 | return sprintf( __( "The domains have been successfully deleted.", $this->textdomain ) ); 716 | } 717 | } 718 | } 719 | 720 | /** 721 | * Modify $current_site global. 722 | */ 723 | function modify_current_site( $value = '' ) { 724 | global $current_site; 725 | $this->current_site = $current_site; 726 | 727 | /* 728 | // Old, unreliable, no idea why it's doing this, don't do this 729 | if( empty( $value ) ) { 730 | $value->domain = ''; 731 | } 732 | $current_site->domain = $value->domain; 733 | */ 734 | 735 | if (is_object($value) && isset($value->domain)) $current_site->domain = $value->domain; 736 | else $current_site->domain = ''; 737 | } 738 | 739 | /** 740 | * Restore $current_site global. 741 | * @deprecated 1.3.4.1 742 | */ 743 | function restore_current_site() { 744 | return; 745 | global $current_site; 746 | $current_site = $this->current_site; 747 | $this->current_site = ''; 748 | } 749 | 750 | /** 751 | * Set $current_site and $domain globals with values chosen by the user. 752 | */ 753 | function set_registration_globals( $blogname = '' ) { 754 | global $domain, $current_site; 755 | 756 | if ( isset( $_POST['domain'] ) ) { 757 | $current_site->domain = $_POST['domain']; 758 | if ( is_subdomain_install() && is_user_logged_in() ) { 759 | $blogname = isset( $_POST['blogname'] ) ? $_POST['blogname'] : ''; 760 | } 761 | 762 | $domain = $_POST['domain']; 763 | 764 | //$this->modify_current_site( $current_site ); 765 | // This is just wrong on so many levels... but it seems to get the job done. 766 | add_action( 'check_admin_referer', create_function( 767 | '$action,$domain="' . $current_site->domain . '"', 768 | 'global $current_site; if ("add-site" == $action || "add-blog" == $action) $current_site->domain=$domain;' 769 | ), 10, 1 ); 770 | 771 | add_filter( 'redirect_network_admin_request', '__return_false' ); 772 | } 773 | 774 | return $blogname; 775 | } 776 | 777 | /** 778 | * Set $current_site and $domain globals with values chosen by the user. Used when the user has already a blog. 779 | */ 780 | function set_other_registration_globals( $meta = '' ) { 781 | $this->set_registration_globals(); 782 | 783 | global $domain; 784 | 785 | if( isset( $_POST['domain'] ) && is_subdomain_install() && is_user_logged_in() ) { 786 | $blogname = isset( $_POST['blogname'] ) ? $_POST['blogname'] : ''; 787 | $domain = $blogname . '.' . $_POST['domain']; 788 | } 789 | 790 | return $meta; 791 | } 792 | 793 | /** 794 | * Set $current_site and $domain globals with values chosen by the user. 795 | */ 796 | function wpmuadminedit() { 797 | global $current_site; 798 | 799 | if( isset( $_POST['domain'] ) && $_GET['action'] == 'addblog' ) 800 | $current_site->domain = $_POST['domain']; 801 | } 802 | 803 | /** 804 | * Add domain choice to signup form. 805 | */ 806 | function extend_signup_blogform() { 807 | 808 | wp_enqueue_script( 'jquery' ); 809 | if ( !defined( 'MD_DEQUEUE_PLACEMENT' ) || !MD_DEQUEUE_PLACEMENT ) { 810 | wp_enqueue_script( 'md-placement', plugins_url( '/js/placement.js', __FILE__ ), array( 'jquery' ) ); 811 | wp_localize_script( 'md-placement', 'l10nMd', array( 'your_address' => __( 'Your address will be', $this->textdomain ) ) ); 812 | } 813 | 814 | if ( count( $domains = $this->domains ) > 1 ) { 815 | $primary = wp_list_filter( $domains, array( 'domain_name' => DOMAIN_CURRENT_SITE ) ); 816 | $else = wp_list_filter( $domains, array( 'domain_name' => DOMAIN_CURRENT_SITE ), 'NOT' ); 817 | 818 | $domains = array_merge( $primary, $else ); 819 | 820 | $super_admin = is_super_admin(); 821 | $show_restricted_domains = $this->show_restricted_domains(); 822 | $posted_domain = isset( $_POST['domain'] ) ? $_POST['domain'] : ''; 823 | 824 | echo ''; 831 | } else { 832 | echo '', $domains[0]['domain_name'], ''; 833 | } 834 | } 835 | 836 | 837 | 838 | /** 839 | * Adds domain choice to the Super Admin New Site form 840 | */ 841 | function extend_admin_blogform() { 842 | global $pagenow, $wp_version; 843 | 844 | $sites_page = version_compare( $wp_version, '3.0.9', '>' ) ? 'site-new.php' : 'ms-sites.php'; 845 | if( $sites_page !== $pagenow || ( isset( $_GET['action'] ) && 'editblog' == $_GET['action'] ) ) { 846 | return; 847 | } 848 | 849 | if( is_subdomain_install() ) { 850 | ?> 851 | 863 | 866 | 879 | 914 | 929 | 936 | 944 | 947 | 955 | 962 | 978 | sunrise, '<' ); 1030 | 1031 | if ( $need_update && is_writable( WP_CONTENT_DIR ) && is_readable( $source ) ) { 1032 | @copy( $source, $dest ); 1033 | } 1034 | } 1035 | } 1036 | 1037 | /** 1038 | * Registers an action hook. 1039 | * 1040 | * @since 1.3.3 1041 | * @uses add_action() To register action hook. 1042 | * 1043 | * @access protected 1044 | * @param string $tag The name of the action to which the $method is hooked. 1045 | * @param string $method The name of the method to be called. 1046 | * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action. 1047 | * @param int $accepted_args optional. The number of arguments the function accept (default 1). 1048 | * @return $this 1049 | */ 1050 | protected function _add_action( $tag, $method = '', $priority = 10, $accepted_args = 1 ) { 1051 | add_action( $tag, array( $this, empty( $method ) ? $tag : $method ), $priority, $accepted_args ); 1052 | return $this; 1053 | } 1054 | 1055 | /** 1056 | * Registers AJAX action hook. 1057 | * 1058 | * @since 1.3.3 1059 | * 1060 | * @access public 1061 | * @param string $tag The name of the AJAX action to which the $method is hooked. 1062 | * @param string $method Optional. The name of the method to be called. If the name of the method is not provided, tag name will be used as method name. 1063 | * @param boolean $private Optional. Determines if we should register hook for logged in users. 1064 | * @param boolean $public Optional. Determines if we should register hook for not logged in users. 1065 | * @return $this 1066 | */ 1067 | protected function _add_ajax_action( $tag, $method = '', $private = true, $public = false ) { 1068 | if ( $private ) { 1069 | $this->_add_action( 'wp_ajax_' . $tag, $method ); 1070 | } 1071 | 1072 | if ( $public ) { 1073 | $this->_add_action( 'wp_ajax_nopriv_' . $tag, $method ); 1074 | } 1075 | 1076 | return $this; 1077 | } 1078 | 1079 | /** 1080 | * Registers a filter hook. 1081 | * 1082 | * @since 1.3.3 1083 | * @uses add_filter() To register filter hook. 1084 | * 1085 | * @access protected 1086 | * @param string $tag The name of the filter to hook the $method to. 1087 | * @param type $method The name of the method to be called when the filter is applied. 1088 | * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action. 1089 | * @param int $accepted_args optional. The number of arguments the function accept (default 1). 1090 | * @return $this 1091 | */ 1092 | protected function _add_filter( $tag, $method = '', $priority = 10, $accepted_args = 1 ) { 1093 | add_filter( $tag, array( $this, empty( $method ) ? $tag : $method ), $priority, $accepted_args ); 1094 | return $this; 1095 | } 1096 | 1097 | 1098 | /** 1099 | * Retrieves domains from the database 1100 | * 1101 | * @since 1.3.4 1102 | * @access protected 1103 | * 1104 | * @return array 1105 | */ 1106 | protected function get_original_domains(){ 1107 | global $wpdb; 1108 | return $wpdb->get_col("SELECT `domain` FROM " . $wpdb->site); 1109 | } 1110 | 1111 | /** 1112 | * Checks if current site resides in original domain 1113 | * 1114 | * @since 1.3.4.6 1115 | * 1116 | * @param string $domain 1117 | * @return bool true if it's original domain, false if not 1118 | */ 1119 | protected function is_original_domain( $domain = null ){ 1120 | 1121 | $domain = parse_url( is_null( $domain ) ? $this->_http->hostinfo : $domain , PHP_URL_HOST ); 1122 | if( is_array( $this->domains ) ){ 1123 | foreach( $this->domains as $key => $domain_item){ 1124 | if( $domain === $domain_item['domain_name'] || strpos($domain, "." . $domain_item['domain_name']) ){ 1125 | return apply_filters("md_is_original_domain", true, $domain); 1126 | } 1127 | } 1128 | } 1129 | 1130 | $is_original_domain = in_array( $domain, $this->get_original_domains() ); 1131 | return apply_filters("md_is_original_domain", $is_original_domain, $domain); 1132 | } 1133 | 1134 | /** 1135 | * Checks if current site resides in mapped domain 1136 | * 1137 | * @since 1.3.4.6 1138 | * 1139 | * @param null $domain 1140 | * 1141 | * @return bool 1142 | */ 1143 | protected function is_mapped_domain( $domain = null ){ 1144 | return !$this->is_original_domain( $domain ); 1145 | } 1146 | 1147 | /** 1148 | * Replaces last occurence of string with $replace string 1149 | * 1150 | * @since 1.3.4.6 1151 | * 1152 | * @param $search 1153 | * @param $replace 1154 | * @param $string 1155 | * 1156 | * @return mixed 1157 | */ 1158 | private function _replace_last_occurrence($search, $replace, $string) 1159 | { 1160 | $pos = strrpos($string, $search); 1161 | 1162 | if($pos !== false) 1163 | $string = substr_replace($string, $replace, $pos, strlen($search)); 1164 | 1165 | return $string; 1166 | } 1167 | 1168 | /** 1169 | * Returns ajax url based on the main domain 1170 | * 1171 | * @since 1.3.4.6 1172 | * @param string $scheme The scheme to use. Default is 'admin', which obeys force_ssl_admin() and is_ssl(). 'http' or 'https' can be passed to force those schemes. 1173 | * @return mixed 1174 | */ 1175 | protected function get_main_ajax_url( $scheme = 'admin' ){ 1176 | return $this->_replace_last_occurrence('network/', '', network_admin_url( 'admin-ajax.php', $scheme ) ); 1177 | } 1178 | } 1179 | 1180 | 1181 | $multi_dm = new multi_domain(); -------------------------------------------------------------------------------- /sunrise.php: -------------------------------------------------------------------------------- 1 | defined("DM_CUSTOM_SUNRISE") ? DM_CUSTOM_SUNRISE : ( defined( "WP_PLUGIN_DIR" ) ? rtrim( WP_PLUGIN_DIR, '/\\' ) . "/domain-mapping/inc/sunrise.php" : dirname( __FILE__ ) . "/plugins/domain-mapping/inc/sunrise.php" ), 4 | "md_sunrise" => defined("MD_CUSTOM_SUNRISE") ? MD_CUSTOM_SUNRISE : ( defined( "WP_PLUGIN_DIR" ) ? rtrim( WP_PLUGIN_DIR, '/\\' ) . "/multi-domains/inc/sunrise.php" : dirname( __FILE__ ) . "/plugins/multi-domains/inc/sunrise.php" ) 5 | ); 6 | 7 | foreach( $sunrises as $sunrise ){ 8 | if( is_readable( $sunrise ) ){ 9 | include $sunrise; 10 | } 11 | } --------------------------------------------------------------------------------