/wp-includes/ms-functions.php

  1. <?php 
  2. /** 
  3. * Multisite WordPress API 
  4. * 
  5. * @package WordPress 
  6. * @subpackage Multisite 
  7. * @since 3.0.0 
  8. */ 
  9.  
  10. /** 
  11. * Gets the network's site and user counts. 
  12. * 
  13. * @since MU 1.0 
  14. * 
  15. * @return array Site and user count for the network. 
  16. */ 
  17. function get_sitestats() { 
  18. $stats = array( 
  19. 'blogs' => get_blog_count(),  
  20. 'users' => get_user_count(),  
  21. ); 
  22.  
  23. return $stats; 
  24.  
  25. /** 
  26. * Get one of a user's active blogs 
  27. * 
  28. * Returns the user's primary blog, if they have one and 
  29. * it is active. If it's inactive, function returns another 
  30. * active blog of the user. If none are found, the user 
  31. * is added as a Subscriber to the Dashboard Blog and that blog 
  32. * is returned. 
  33. * 
  34. * @since MU 1.0 
  35. * 
  36. * @global wpdb $wpdb WordPress database abstraction object. 
  37. * 
  38. * @param int $user_id The unique ID of the user 
  39. * @return WP_Site|void The blog object 
  40. */ 
  41. function get_active_blog_for_user( $user_id ) { 
  42. global $wpdb; 
  43. $blogs = get_blogs_of_user( $user_id ); 
  44. if ( empty( $blogs ) ) 
  45. return; 
  46.  
  47. if ( !is_multisite() ) 
  48. return $blogs[$wpdb->blogid]; 
  49.  
  50. $primary_blog = get_user_meta( $user_id, 'primary_blog', true ); 
  51. $first_blog = current($blogs); 
  52. if ( false !== $primary_blog ) { 
  53. if ( ! isset( $blogs[ $primary_blog ] ) ) { 
  54. update_user_meta( $user_id, 'primary_blog', $first_blog->userblog_id ); 
  55. $primary = get_site( $first_blog->userblog_id ); 
  56. } else { 
  57. $primary = get_site( $primary_blog ); 
  58. } else { 
  59. //TODO Review this call to add_user_to_blog too - to get here the user must have a role on this blog? 
  60. add_user_to_blog( $first_blog->userblog_id, $user_id, 'subscriber' ); 
  61. update_user_meta( $user_id, 'primary_blog', $first_blog->userblog_id ); 
  62. $primary = $first_blog; 
  63.  
  64. if ( ( ! is_object( $primary ) ) || ( $primary->archived == 1 || $primary->spam == 1 || $primary->deleted == 1 ) ) { 
  65. $blogs = get_blogs_of_user( $user_id, true ); // if a user's primary blog is shut down, check their other blogs. 
  66. $ret = false; 
  67. if ( is_array( $blogs ) && count( $blogs ) > 0 ) { 
  68. foreach ( (array) $blogs as $blog_id => $blog ) { 
  69. if ( $blog->site_id != $wpdb->siteid ) 
  70. continue; 
  71. $details = get_site( $blog_id ); 
  72. if ( is_object( $details ) && $details->archived == 0 && $details->spam == 0 && $details->deleted == 0 ) { 
  73. $ret = $blog; 
  74. if ( get_user_meta( $user_id , 'primary_blog', true ) != $blog_id ) 
  75. update_user_meta( $user_id, 'primary_blog', $blog_id ); 
  76. if ( !get_user_meta($user_id , 'source_domain', true) ) 
  77. update_user_meta( $user_id, 'source_domain', $blog->domain ); 
  78. break; 
  79. } else { 
  80. return; 
  81. return $ret; 
  82. } else { 
  83. return $primary; 
  84.  
  85. /** 
  86. * The number of active users in your installation. 
  87. * 
  88. * The count is cached and updated twice daily. This is not a live count. 
  89. * 
  90. * @since MU 2.7 
  91. * 
  92. * @return int 
  93. */ 
  94. function get_user_count() { 
  95. return get_site_option( 'user_count' ); 
  96.  
  97. /** 
  98. * The number of active sites on your installation. 
  99. * 
  100. * The count is cached and updated twice daily. This is not a live count. 
  101. * 
  102. * @since MU 1.0 
  103. * 
  104. * @param int $network_id Deprecated, not supported. 
  105. * @return int 
  106. */ 
  107. function get_blog_count( $network_id = 0 ) { 
  108. if ( func_num_args() ) 
  109. _deprecated_argument( __FUNCTION__, '3.1.0' ); 
  110.  
  111. return get_site_option( 'blog_count' ); 
  112.  
  113. /** 
  114. * Get a blog post from any site on the network. 
  115. * 
  116. * @since MU 1.0 
  117. * 
  118. * @param int $blog_id ID of the blog. 
  119. * @param int $post_id ID of the post you're looking for. 
  120. * @return WP_Post|null WP_Post on success or null on failure 
  121. */ 
  122. function get_blog_post( $blog_id, $post_id ) { 
  123. switch_to_blog( $blog_id ); 
  124. $post = get_post( $post_id ); 
  125. restore_current_blog(); 
  126.  
  127. return $post; 
  128.  
  129. /** 
  130. * Adds a user to a blog. 
  131. * 
  132. * Use the {@see 'add_user_to_blog'} action to fire an event when users are added to a blog. 
  133. * 
  134. * @since MU 1.0 
  135. * 
  136. * @param int $blog_id ID of the blog you're adding the user to. 
  137. * @param int $user_id ID of the user you're adding. 
  138. * @param string $role The role you want the user to have 
  139. * @return true|WP_Error 
  140. */ 
  141. function add_user_to_blog( $blog_id, $user_id, $role ) { 
  142. switch_to_blog($blog_id); 
  143.  
  144. $user = get_userdata( $user_id ); 
  145.  
  146. if ( ! $user ) { 
  147. restore_current_blog(); 
  148. return new WP_Error( 'user_does_not_exist', __( 'The requested user does not exist.' ) ); 
  149.  
  150. if ( !get_user_meta($user_id, 'primary_blog', true) ) { 
  151. update_user_meta($user_id, 'primary_blog', $blog_id); 
  152. $site = get_site( $blog_id ); 
  153. update_user_meta( $user_id, 'source_domain', $site->domain ); 
  154.  
  155. $user->set_role($role); 
  156.  
  157. /** 
  158. * Fires immediately after a user is added to a site. 
  159. * 
  160. * @since MU 
  161. * 
  162. * @param int $user_id User ID. 
  163. * @param string $role User role. 
  164. * @param int $blog_id Blog ID. 
  165. */ 
  166. do_action( 'add_user_to_blog', $user_id, $role, $blog_id ); 
  167. wp_cache_delete( $user_id, 'users' ); 
  168. wp_cache_delete( $blog_id . '_user_count', 'blog-details' ); 
  169. restore_current_blog(); 
  170. return true; 
  171.  
  172. /** 
  173. * Remove a user from a blog. 
  174. * 
  175. * Use the {@see 'remove_user_from_blog'} action to fire an event when 
  176. * users are removed from a blog. 
  177. * 
  178. * Accepts an optional `$reassign` parameter, if you want to 
  179. * reassign the user's blog posts to another user upon removal. 
  180. * 
  181. * @since MU 1.0 
  182. * 
  183. * @global wpdb $wpdb WordPress database abstraction object. 
  184. * 
  185. * @param int $user_id ID of the user you're removing. 
  186. * @param int $blog_id ID of the blog you're removing the user from. 
  187. * @param string $reassign Optional. A user to whom to reassign posts. 
  188. * @return true|WP_Error 
  189. */ 
  190. function remove_user_from_blog($user_id, $blog_id = '', $reassign = '') { 
  191. global $wpdb; 
  192. switch_to_blog($blog_id); 
  193. $user_id = (int) $user_id; 
  194. /** 
  195. * Fires before a user is removed from a site. 
  196. * 
  197. * @since MU 
  198. * 
  199. * @param int $user_id User ID. 
  200. * @param int $blog_id Blog ID. 
  201. */ 
  202. do_action( 'remove_user_from_blog', $user_id, $blog_id ); 
  203.  
  204. // If being removed from the primary blog, set a new primary if the user is assigned 
  205. // to multiple blogs. 
  206. $primary_blog = get_user_meta($user_id, 'primary_blog', true); 
  207. if ( $primary_blog == $blog_id ) { 
  208. $new_id = ''; 
  209. $new_domain = ''; 
  210. $blogs = get_blogs_of_user($user_id); 
  211. foreach ( (array) $blogs as $blog ) { 
  212. if ( $blog->userblog_id == $blog_id ) 
  213. continue; 
  214. $new_id = $blog->userblog_id; 
  215. $new_domain = $blog->domain; 
  216. break; 
  217.  
  218. update_user_meta($user_id, 'primary_blog', $new_id); 
  219. update_user_meta($user_id, 'source_domain', $new_domain); 
  220.  
  221. // wp_revoke_user($user_id); 
  222. $user = get_userdata( $user_id ); 
  223. if ( ! $user ) { 
  224. restore_current_blog(); 
  225. return new WP_Error('user_does_not_exist', __('That user does not exist.')); 
  226.  
  227. $user->remove_all_caps(); 
  228.  
  229. $blogs = get_blogs_of_user($user_id); 
  230. if ( count($blogs) == 0 ) { 
  231. update_user_meta($user_id, 'primary_blog', ''); 
  232. update_user_meta($user_id, 'source_domain', ''); 
  233.  
  234. if ( $reassign != '' ) { 
  235. $reassign = (int) $reassign; 
  236. $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_author = %d", $user_id ) ); 
  237. $link_ids = $wpdb->get_col( $wpdb->prepare( "SELECT link_id FROM $wpdb->links WHERE link_owner = %d", $user_id ) ); 
  238.  
  239. if ( ! empty( $post_ids ) ) { 
  240. $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET post_author = %d WHERE post_author = %d", $reassign, $user_id ) ); 
  241. array_walk( $post_ids, 'clean_post_cache' ); 
  242.  
  243. if ( ! empty( $link_ids ) ) { 
  244. $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->links SET link_owner = %d WHERE link_owner = %d", $reassign, $user_id ) ); 
  245. array_walk( $link_ids, 'clean_bookmark_cache' ); 
  246.  
  247. restore_current_blog(); 
  248.  
  249. return true; 
  250.  
  251. /** 
  252. * Get the permalink for a post on another blog. 
  253. * 
  254. * @since MU 1.0 
  255. * 
  256. * @param int $blog_id ID of the source blog. 
  257. * @param int $post_id ID of the desired post. 
  258. * @return string The post's permalink 
  259. */ 
  260. function get_blog_permalink( $blog_id, $post_id ) { 
  261. switch_to_blog( $blog_id ); 
  262. $link = get_permalink( $post_id ); 
  263. restore_current_blog(); 
  264.  
  265. return $link; 
  266.  
  267. /** 
  268. * Get a blog's numeric ID from its URL. 
  269. * 
  270. * On a subdirectory installation like example.com/blog1/,  
  271. * $domain will be the root 'example.com' and $path the 
  272. * subdirectory '/blog1/'. With subdomains like blog1.example.com,  
  273. * $domain is 'blog1.example.com' and $path is '/'. 
  274. * 
  275. * @since MU 2.6.5 
  276. * 
  277. * @global wpdb $wpdb WordPress database abstraction object. 
  278. * 
  279. * @param string $domain 
  280. * @param string $path Optional. Not required for subdomain installations. 
  281. * @return int 0 if no blog found, otherwise the ID of the matching blog 
  282. */ 
  283. function get_blog_id_from_url( $domain, $path = '/' ) { 
  284. $domain = strtolower( $domain ); 
  285. $path = strtolower( $path ); 
  286. $id = wp_cache_get( md5( $domain . $path ), 'blog-id-cache' ); 
  287.  
  288. if ( $id == -1 ) // blog does not exist 
  289. return 0; 
  290. elseif ( $id ) 
  291. return (int) $id; 
  292.  
  293. $args = array( 
  294. 'domain' => $domain,  
  295. 'path' => $path,  
  296. 'fields' => 'ids',  
  297. ); 
  298. $result = get_sites( $args ); 
  299. $id = array_shift( $result ); 
  300.  
  301. if ( ! $id ) { 
  302. wp_cache_set( md5( $domain . $path ), -1, 'blog-id-cache' ); 
  303. return 0; 
  304.  
  305. wp_cache_set( md5( $domain . $path ), $id, 'blog-id-cache' ); 
  306.  
  307. return $id; 
  308.  
  309. // Admin functions 
  310.  
  311. /** 
  312. * Checks an email address against a list of banned domains. 
  313. * 
  314. * This function checks against the Banned Email Domains list 
  315. * at wp-admin/network/settings.php. The check is only run on 
  316. * self-registrations; user creation at wp-admin/network/users.php 
  317. * bypasses this check. 
  318. * 
  319. * @since MU 
  320. * 
  321. * @param string $user_email The email provided by the user at registration. 
  322. * @return bool Returns true when the email address is banned. 
  323. */ 
  324. function is_email_address_unsafe( $user_email ) { 
  325. $banned_names = get_site_option( 'banned_email_domains' ); 
  326. if ( $banned_names && ! is_array( $banned_names ) ) 
  327. $banned_names = explode( "\n", $banned_names ); 
  328.  
  329. $is_email_address_unsafe = false; 
  330.  
  331. if ( $banned_names && is_array( $banned_names ) ) { 
  332. $banned_names = array_map( 'strtolower', $banned_names ); 
  333. $normalized_email = strtolower( $user_email ); 
  334.  
  335. list( $email_local_part, $email_domain ) = explode( '@', $normalized_email ); 
  336.  
  337. foreach ( $banned_names as $banned_domain ) { 
  338. if ( ! $banned_domain ) 
  339. continue; 
  340.  
  341. if ( $email_domain == $banned_domain ) { 
  342. $is_email_address_unsafe = true; 
  343. break; 
  344.  
  345. $dotted_domain = ".$banned_domain"; 
  346. if ( $dotted_domain === substr( $normalized_email, -strlen( $dotted_domain ) ) ) { 
  347. $is_email_address_unsafe = true; 
  348. break; 
  349.  
  350. /** 
  351. * Filters whether an email address is unsafe. 
  352. * 
  353. * @since 3.5.0 
  354. * 
  355. * @param bool $is_email_address_unsafe Whether the email address is "unsafe". Default false. 
  356. * @param string $user_email User email address. 
  357. */ 
  358. return apply_filters( 'is_email_address_unsafe', $is_email_address_unsafe, $user_email ); 
  359.  
  360. /** 
  361. * Sanitize and validate data required for a user sign-up. 
  362. * 
  363. * Verifies the validity and uniqueness of user names and user email addresses,  
  364. * and checks email addresses against admin-provided domain whitelists and blacklists. 
  365. * 
  366. * The {@see 'wpmu_validate_user_signup'} hook provides an easy way to modify the sign-up 
  367. * process. The value $result, which is passed to the hook, contains both the user-provided 
  368. * info and the error messages created by the function. {@see 'wpmu_validate_user_signup'} 
  369. * allows you to process the data in any way you'd like, and unset the relevant errors if 
  370. * necessary. 
  371. * 
  372. * @since MU 
  373. * 
  374. * @global wpdb $wpdb WordPress database abstraction object. 
  375. * 
  376. * @param string $user_name The login name provided by the user. 
  377. * @param string $user_email The email provided by the user. 
  378. * @return array Contains username, email, and error messages. 
  379. */ 
  380. function wpmu_validate_user_signup($user_name, $user_email) { 
  381. global $wpdb; 
  382.  
  383. $errors = new WP_Error(); 
  384.  
  385. $orig_username = $user_name; 
  386. $user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) ); 
  387.  
  388. if ( $user_name != $orig_username || preg_match( '/[^a-z0-9]/', $user_name ) ) { 
  389. $errors->add( 'user_name', __( 'Usernames can only contain lowercase letters (a-z) and numbers.' ) ); 
  390. $user_name = $orig_username; 
  391.  
  392. $user_email = sanitize_email( $user_email ); 
  393.  
  394. if ( empty( $user_name ) ) 
  395. $errors->add('user_name', __( 'Please enter a username.' ) ); 
  396.  
  397. $illegal_names = get_site_option( 'illegal_names' ); 
  398. if ( ! is_array( $illegal_names ) ) { 
  399. $illegal_names = array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' ); 
  400. add_site_option( 'illegal_names', $illegal_names ); 
  401. if ( in_array( $user_name, $illegal_names ) ) { 
  402. $errors->add( 'user_name', __( 'Sorry, that username is not allowed.' ) ); 
  403.  
  404. /** This filter is documented in wp-includes/user.php */ 
  405. $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() ); 
  406.  
  407. if ( in_array( strtolower( $user_name ), array_map( 'strtolower', $illegal_logins ) ) ) { 
  408. $errors->add( 'user_name', __( 'Sorry, that username is not allowed.' ) ); 
  409.  
  410. if ( is_email_address_unsafe( $user_email ) ) 
  411. $errors->add('user_email', __('You cannot use that email address to signup. We are having problems with them blocking some of our email. Please use another email provider.')); 
  412.  
  413. if ( strlen( $user_name ) < 4 ) 
  414. $errors->add('user_name', __( 'Username must be at least 4 characters.' ) ); 
  415.  
  416. if ( strlen( $user_name ) > 60 ) { 
  417. $errors->add( 'user_name', __( 'Username may not be longer than 60 characters.' ) ); 
  418.  
  419. // all numeric? 
  420. if ( preg_match( '/^[0-9]*$/', $user_name ) ) 
  421. $errors->add('user_name', __('Sorry, usernames must have letters too!')); 
  422.  
  423. if ( !is_email( $user_email ) ) 
  424. $errors->add('user_email', __( 'Please enter a valid email address.' ) ); 
  425.  
  426. $limited_email_domains = get_site_option( 'limited_email_domains' ); 
  427. if ( is_array( $limited_email_domains ) && ! empty( $limited_email_domains ) ) { 
  428. $emaildomain = substr( $user_email, 1 + strpos( $user_email, '@' ) ); 
  429. if ( ! in_array( $emaildomain, $limited_email_domains ) ) { 
  430. $errors->add('user_email', __('Sorry, that email address is not allowed!')); 
  431.  
  432. // Check if the username has been used already. 
  433. if ( username_exists($user_name) ) 
  434. $errors->add( 'user_name', __( 'Sorry, that username already exists!' ) ); 
  435.  
  436. // Check if the email address has been used already. 
  437. if ( email_exists($user_email) ) 
  438. $errors->add( 'user_email', __( 'Sorry, that email address is already used!' ) ); 
  439.  
  440. // Has someone already signed up for this username? 
  441. $signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_login = %s", $user_name) ); 
  442. if ( $signup != null ) { 
  443. $registered_at = mysql2date('U', $signup->registered); 
  444. $now = current_time( 'timestamp', true ); 
  445. $diff = $now - $registered_at; 
  446. // If registered more than two days ago, cancel registration and let this signup go through. 
  447. if ( $diff > 2 * DAY_IN_SECONDS ) 
  448. $wpdb->delete( $wpdb->signups, array( 'user_login' => $user_name ) ); 
  449. else 
  450. $errors->add('user_name', __('That username is currently reserved but may be available in a couple of days.')); 
  451.  
  452. $signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE user_email = %s", $user_email) ); 
  453. if ( $signup != null ) { 
  454. $diff = current_time( 'timestamp', true ) - mysql2date('U', $signup->registered); 
  455. // If registered more than two days ago, cancel registration and let this signup go through. 
  456. if ( $diff > 2 * DAY_IN_SECONDS ) 
  457. $wpdb->delete( $wpdb->signups, array( 'user_email' => $user_email ) ); 
  458. else 
  459. $errors->add('user_email', __('That email address has already been used. Please check your inbox for an activation email. It will become available in a couple of days if you do nothing.')); 
  460.  
  461. $result = array('user_name' => $user_name, 'orig_username' => $orig_username, 'user_email' => $user_email, 'errors' => $errors); 
  462.  
  463. /** 
  464. * Filters the validated user registration details. 
  465. * 
  466. * This does not allow you to override the username or email of the user during 
  467. * registration. The values are solely used for validation and error handling. 
  468. * 
  469. * @since MU 
  470. * 
  471. * @param array $result { 
  472. * The array of user name, email and the error messages. 
  473. * 
  474. * @type string $user_name Sanitized and unique username. 
  475. * @type string $orig_username Original username. 
  476. * @type string $user_email User email address. 
  477. * @type WP_Error $errors WP_Error object containing any errors found. 
  478. * } 
  479. */ 
  480. return apply_filters( 'wpmu_validate_user_signup', $result ); 
  481.  
  482. /** 
  483. * Processes new site registrations. 
  484. * 
  485. * Checks the data provided by the user during blog signup. Verifies 
  486. * the validity and uniqueness of blog paths and domains. 
  487. * 
  488. * This function prevents the current user from registering a new site 
  489. * with a blogname equivalent to another user's login name. Passing the 
  490. * $user parameter to the function, where $user is the other user, is 
  491. * effectively an override of this limitation. 
  492. * 
  493. * Filter {@see 'wpmu_validate_blog_signup'} if you want to modify 
  494. * the way that WordPress validates new site signups. 
  495. * 
  496. * @since MU 
  497. * 
  498. * @global wpdb $wpdb 
  499. * @global string $domain 
  500. * 
  501. * @param string $blogname The blog name provided by the user. Must be unique. 
  502. * @param string $blog_title The blog title provided by the user. 
  503. * @param WP_User|string $user Optional. The user object to check against the new site name. 
  504. * @return array Contains the new site data and error messages. 
  505. */ 
  506. function wpmu_validate_blog_signup( $blogname, $blog_title, $user = '' ) { 
  507. global $wpdb, $domain; 
  508.  
  509. $current_network = get_network(); 
  510. $base = $current_network->path; 
  511.  
  512. $blog_title = strip_tags( $blog_title ); 
  513.  
  514. $errors = new WP_Error(); 
  515. $illegal_names = get_site_option( 'illegal_names' ); 
  516. if ( $illegal_names == false ) { 
  517. $illegal_names = array( 'www', 'web', 'root', 'admin', 'main', 'invite', 'administrator' ); 
  518. add_site_option( 'illegal_names', $illegal_names ); 
  519.  
  520. /** 
  521. * On sub dir installs, some names are so illegal, only a filter can 
  522. * spring them from jail. 
  523. */ 
  524. if ( ! is_subdomain_install() ) { 
  525. $illegal_names = array_merge( $illegal_names, get_subdirectory_reserved_names() ); 
  526.  
  527. if ( empty( $blogname ) ) 
  528. $errors->add('blogname', __( 'Please enter a site name.' ) ); 
  529.  
  530. if ( preg_match( '/[^a-z0-9]+/', $blogname ) ) { 
  531. $errors->add( 'blogname', __( 'Site names can only contain lowercase letters (a-z) and numbers.' ) ); 
  532.  
  533. if ( in_array( $blogname, $illegal_names ) ) 
  534. $errors->add('blogname', __( 'That name is not allowed.' ) ); 
  535.  
  536. if ( strlen( $blogname ) < 4 && !is_super_admin() ) 
  537. $errors->add('blogname', __( 'Site name must be at least 4 characters.' ) ); 
  538.  
  539. // do not allow users to create a blog that conflicts with a page on the main blog. 
  540. if ( !is_subdomain_install() && $wpdb->get_var( $wpdb->prepare( "SELECT post_name FROM " . $wpdb->get_blog_prefix( $current_network->site_id ) . "posts WHERE post_type = 'page' AND post_name = %s", $blogname ) ) ) 
  541. $errors->add( 'blogname', __( 'Sorry, you may not use that site name.' ) ); 
  542.  
  543. // all numeric? 
  544. if ( preg_match( '/^[0-9]*$/', $blogname ) ) 
  545. $errors->add('blogname', __('Sorry, site names must have letters too!')); 
  546.  
  547. /** 
  548. * Filters the new site name during registration. 
  549. * 
  550. * The name is the site's subdomain or the site's subdirectory 
  551. * path depending on the network settings. 
  552. * 
  553. * @since MU 
  554. * 
  555. * @param string $blogname Site name. 
  556. */ 
  557. $blogname = apply_filters( 'newblogname', $blogname ); 
  558.  
  559. $blog_title = wp_unslash( $blog_title ); 
  560.  
  561. if ( empty( $blog_title ) ) 
  562. $errors->add('blog_title', __( 'Please enter a site title.' ) ); 
  563.  
  564. // Check if the domain/path has been used already. 
  565. if ( is_subdomain_install() ) { 
  566. $mydomain = $blogname . '.' . preg_replace( '|^www\.|', '', $domain ); 
  567. $path = $base; 
  568. } else { 
  569. $mydomain = "$domain"; 
  570. $path = $base.$blogname.'/'; 
  571. if ( domain_exists($mydomain, $path, $current_network->id) ) 
  572. $errors->add( 'blogname', __( 'Sorry, that site already exists!' ) ); 
  573.  
  574. if ( username_exists( $blogname ) ) { 
  575. if ( ! is_object( $user ) || ( is_object($user) && ( $user->user_login != $blogname ) ) ) 
  576. $errors->add( 'blogname', __( 'Sorry, that site is reserved!' ) ); 
  577.  
  578. // Has someone already signed up for this domain? 
  579. $signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE domain = %s AND path = %s", $mydomain, $path) ); // TODO: Check email too? 
  580. if ( ! empty($signup) ) { 
  581. $diff = current_time( 'timestamp', true ) - mysql2date('U', $signup->registered); 
  582. // If registered more than two days ago, cancel registration and let this signup go through. 
  583. if ( $diff > 2 * DAY_IN_SECONDS ) 
  584. $wpdb->delete( $wpdb->signups, array( 'domain' => $mydomain , 'path' => $path ) ); 
  585. else 
  586. $errors->add('blogname', __('That site is currently reserved but may be available in a couple days.')); 
  587.  
  588. $result = array('domain' => $mydomain, 'path' => $path, 'blogname' => $blogname, 'blog_title' => $blog_title, 'user' => $user, 'errors' => $errors); 
  589.  
  590. /** 
  591. * Filters site details and error messages following registration. 
  592. * 
  593. * @since MU 
  594. * 
  595. * @param array $result { 
  596. * Array of domain, path, blog name, blog title, user and error messages. 
  597. * 
  598. * @type string $domain Domain for the site. 
  599. * @type string $path Path for the site. Used in subdirectory installs. 
  600. * @type string $blogname The unique site name (slug). 
  601. * @type string $blog_title Blog title. 
  602. * @type string|WP_User $user By default, an empty string. A user object if provided. 
  603. * @type WP_Error $errors WP_Error containing any errors found. 
  604. * } 
  605. */ 
  606. return apply_filters( 'wpmu_validate_blog_signup', $result ); 
  607.  
  608. /** 
  609. * Record site signup information for future activation. 
  610. * 
  611. * @since MU 
  612. * 
  613. * @global wpdb $wpdb WordPress database abstraction object. 
  614. * 
  615. * @param string $domain The requested domain. 
  616. * @param string $path The requested path. 
  617. * @param string $title The requested site title. 
  618. * @param string $user The user's requested login name. 
  619. * @param string $user_email The user's email address. 
  620. * @param array $meta By default, contains the requested privacy setting and lang_id. 
  621. */ 
  622. function wpmu_signup_blog( $domain, $path, $title, $user, $user_email, $meta = array() ) { 
  623. global $wpdb; 
  624.  
  625. $key = substr( md5( time() . wp_rand() . $domain ), 0, 16 ); 
  626. $meta = serialize($meta); 
  627.  
  628. $wpdb->insert( $wpdb->signups, array( 
  629. 'domain' => $domain,  
  630. 'path' => $path,  
  631. 'title' => $title,  
  632. 'user_login' => $user,  
  633. 'user_email' => $user_email,  
  634. 'registered' => current_time('mysql', true),  
  635. 'activation_key' => $key,  
  636. 'meta' => $meta 
  637. ) ); 
  638.  
  639. /** 
  640. * Fires after site signup information has been written to the database. 
  641. * 
  642. * @since 4.4.0 
  643. * 
  644. * @param string $domain The requested domain. 
  645. * @param string $path The requested path. 
  646. * @param string $title The requested site title. 
  647. * @param string $user The user's requested login name. 
  648. * @param string $user_email The user's email address. 
  649. * @param string $key The user's activation key 
  650. * @param array $meta By default, contains the requested privacy setting and lang_id. 
  651. */ 
  652. do_action( 'after_signup_site', $domain, $path, $title, $user, $user_email, $key, $meta ); 
  653.  
  654. /** 
  655. * Record user signup information for future activation. 
  656. * 
  657. * This function is used when user registration is open but 
  658. * new site registration is not. 
  659. * 
  660. * @since MU 
  661. * 
  662. * @global wpdb $wpdb WordPress database abstraction object. 
  663. * 
  664. * @param string $user The user's requested login name. 
  665. * @param string $user_email The user's email address. 
  666. * @param array $meta By default, this is an empty array. 
  667. */ 
  668. function wpmu_signup_user( $user, $user_email, $meta = array() ) { 
  669. global $wpdb; 
  670.  
  671. // Format data 
  672. $user = preg_replace( '/\s+/', '', sanitize_user( $user, true ) ); 
  673. $user_email = sanitize_email( $user_email ); 
  674. $key = substr( md5( time() . wp_rand() . $user_email ), 0, 16 ); 
  675. $meta = serialize($meta); 
  676.  
  677. $wpdb->insert( $wpdb->signups, array( 
  678. 'domain' => '',  
  679. 'path' => '',  
  680. 'title' => '',  
  681. 'user_login' => $user,  
  682. 'user_email' => $user_email,  
  683. 'registered' => current_time('mysql', true),  
  684. 'activation_key' => $key,  
  685. 'meta' => $meta 
  686. ) ); 
  687.  
  688. /** 
  689. * Fires after a user's signup information has been written to the database. 
  690. * 
  691. * @since 4.4.0 
  692. * 
  693. * @param string $user The user's requested login name. 
  694. * @param string $user_email The user's email address. 
  695. * @param string $key The user's activation key 
  696. * @param array $meta Additional signup meta. By default, this is an empty array. 
  697. */ 
  698. do_action( 'after_signup_user', $user, $user_email, $key, $meta ); 
  699.  
  700. /** 
  701. * Notify user of signup success. 
  702. * 
  703. * This is the notification function used when site registration 
  704. * is enabled. 
  705. * 
  706. * Filter {@see 'wpmu_signup_blog_notification'} to bypass this function or 
  707. * replace it with your own notification behavior. 
  708. * 
  709. * Filter {@see 'wpmu_signup_blog_notification_email'} and 
  710. * {@see 'wpmu_signup_blog_notification_subject'} to change the content 
  711. * and subject line of the email sent to newly registered users. 
  712. * 
  713. * @since MU 
  714. * 
  715. * @param string $domain The new blog domain. 
  716. * @param string $path The new blog path. 
  717. * @param string $title The site title. 
  718. * @param string $user_login The user's login name. 
  719. * @param string $user_email The user's email address. 
  720. * @param string $key The activation key created in wpmu_signup_blog() 
  721. * @param array $meta By default, contains the requested privacy setting and lang_id. 
  722. * @return bool 
  723. */ 
  724. function wpmu_signup_blog_notification( $domain, $path, $title, $user_login, $user_email, $key, $meta = array() ) { 
  725. /** 
  726. * Filters whether to bypass the new site email notification. 
  727. * 
  728. * @since MU 
  729. * 
  730. * @param string|bool $domain Site domain. 
  731. * @param string $path Site path. 
  732. * @param string $title Site title. 
  733. * @param string $user_login User login name. 
  734. * @param string $user_email User email address. 
  735. * @param string $key Activation key created in wpmu_signup_blog(). 
  736. * @param array $meta By default, contains the requested privacy setting and lang_id. 
  737. */ 
  738. if ( ! apply_filters( 'wpmu_signup_blog_notification', $domain, $path, $title, $user_login, $user_email, $key, $meta ) ) { 
  739. return false; 
  740.  
  741. // Send email with activation link. 
  742. if ( !is_subdomain_install() || get_current_network_id() != 1 ) 
  743. $activate_url = network_site_url("wp-activate.php?key=$key"); 
  744. else 
  745. $activate_url = "http://{$domain}{$path}wp-activate.php?key=$key"; // @todo use *_url() API 
  746.  
  747. $activate_url = esc_url($activate_url); 
  748. $admin_email = get_site_option( 'admin_email' ); 
  749. if ( $admin_email == '' ) 
  750. $admin_email = 'support@' . $_SERVER['SERVER_NAME']; 
  751. $from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) ); 
  752. $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; 
  753.  
  754. $user = get_user_by( 'login', $user_login ); 
  755. $switched_locale = switch_to_locale( get_user_locale( $user ) ); 
  756.  
  757. $message = sprintf( 
  758. /** 
  759. * Filters the message content of the new blog notification email. 
  760. * 
  761. * Content should be formatted for transmission via wp_mail(). 
  762. * 
  763. * @since MU 
  764. * 
  765. * @param string $content Content of the notification email. 
  766. * @param string $domain Site domain. 
  767. * @param string $path Site path. 
  768. * @param string $title Site title. 
  769. * @param string $user_login User login name. 
  770. * @param string $user_email User email address. 
  771. * @param string $key Activation key created in wpmu_signup_blog(). 
  772. * @param array $meta By default, contains the requested privacy setting and lang_id. 
  773. */ 
  774. apply_filters( 'wpmu_signup_blog_notification_email',  
  775. __( "To activate your blog, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%s" ),  
  776. $domain, $path, $title, $user_login, $user_email, $key, $meta 
  777. ),  
  778. $activate_url,  
  779. esc_url( "http://{$domain}{$path}" ),  
  780. $key 
  781. ); 
  782. // TODO: Don't hard code activation link. 
  783. $subject = sprintf( 
  784. /** 
  785. * Filters the subject of the new blog notification email. 
  786. * 
  787. * @since MU 
  788. * 
  789. * @param string $subject Subject of the notification email. 
  790. * @param string $domain Site domain. 
  791. * @param string $path Site path. 
  792. * @param string $title Site title. 
  793. * @param string $user_login User login name. 
  794. * @param string $user_email User email address. 
  795. * @param string $key Activation key created in wpmu_signup_blog(). 
  796. * @param array $meta By default, contains the requested privacy setting and lang_id. 
  797. */ 
  798. apply_filters( 'wpmu_signup_blog_notification_subject',  
  799. /** translators: New site notification email subject. 1: Network name, 2: New site URL */ 
  800. _x( '[%1$s] Activate %2$s', 'New site notification email subject' ),  
  801. $domain, $path, $title, $user_login, $user_email, $key, $meta 
  802. ),  
  803. $from_name,  
  804. esc_url( 'http://' . $domain . $path ) 
  805. ); 
  806. wp_mail( $user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 
  807.  
  808. if ( $switched_locale ) { 
  809. restore_previous_locale(); 
  810.  
  811. return true; 
  812.  
  813. /** 
  814. * Notify user of signup success. 
  815. * 
  816. * This is the notification function used when no new site has 
  817. * been requested. 
  818. * 
  819. * Filter {@see 'wpmu_signup_user_notification'} to bypass this function or 
  820. * replace it with your own notification behavior. 
  821. * 
  822. * Filter {@see 'wpmu_signup_user_notification_email'} and 
  823. * {@see 'wpmu_signup_user_notification_subject'} to change the content 
  824. * and subject line of the email sent to newly registered users. 
  825. * 
  826. * @since MU 
  827. * 
  828. * @param string $user_login The user's login name. 
  829. * @param string $user_email The user's email address. 
  830. * @param string $key The activation key created in wpmu_signup_user() 
  831. * @param array $meta By default, an empty array. 
  832. * @return bool 
  833. */ 
  834. function wpmu_signup_user_notification( $user_login, $user_email, $key, $meta = array() ) { 
  835. /** 
  836. * Filters whether to bypass the email notification for new user sign-up. 
  837. * 
  838. * @since MU 
  839. * 
  840. * @param string $user_login User login name. 
  841. * @param string $user_email User email address. 
  842. * @param string $key Activation key created in wpmu_signup_user(). 
  843. * @param array $meta Signup meta data. 
  844. */ 
  845. if ( ! apply_filters( 'wpmu_signup_user_notification', $user_login, $user_email, $key, $meta ) ) 
  846. return false; 
  847.  
  848. $user = get_user_by( 'login', $user_login ); 
  849. $switched_locale = switch_to_locale( get_user_locale( $user ) ); 
  850.  
  851. // Send email with activation link. 
  852. $admin_email = get_site_option( 'admin_email' ); 
  853. if ( $admin_email == '' ) 
  854. $admin_email = 'support@' . $_SERVER['SERVER_NAME']; 
  855. $from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) ); 
  856. $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; 
  857. $message = sprintf( 
  858. /** 
  859. * Filters the content of the notification email for new user sign-up. 
  860. * 
  861. * Content should be formatted for transmission via wp_mail(). 
  862. * 
  863. * @since MU 
  864. * 
  865. * @param string $content Content of the notification email. 
  866. * @param string $user_login User login name. 
  867. * @param string $user_email User email address. 
  868. * @param string $key Activation key created in wpmu_signup_user(). 
  869. * @param array $meta Signup meta data. 
  870. */ 
  871. apply_filters( 'wpmu_signup_user_notification_email',  
  872. __( "To activate your user, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login." ),  
  873. $user_login, $user_email, $key, $meta 
  874. ),  
  875. site_url( "wp-activate.php?key=$key" ) 
  876. ); 
  877. // TODO: Don't hard code activation link. 
  878. $subject = sprintf( 
  879. /** 
  880. * Filters the subject of the notification email of new user signup. 
  881. * 
  882. * @since MU 
  883. * 
  884. * @param string $subject Subject of the notification email. 
  885. * @param string $user_login User login name. 
  886. * @param string $user_email User email address. 
  887. * @param string $key Activation key created in wpmu_signup_user(). 
  888. * @param array $meta Signup meta data. 
  889. */ 
  890. apply_filters( 'wpmu_signup_user_notification_subject',  
  891. /** translators: New user notification email subject. 1: Network name, 2: New user login */ 
  892. _x( '[%1$s] Activate %2$s', 'New user notification email subject' ),  
  893. $user_login, $user_email, $key, $meta 
  894. ),  
  895. $from_name,  
  896. $user_login 
  897. ); 
  898. wp_mail( $user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 
  899.  
  900. if ( $switched_locale ) { 
  901. restore_previous_locale(); 
  902.  
  903. return true; 
  904.  
  905. /** 
  906. * Activate a signup. 
  907. * 
  908. * Hook to {@see 'wpmu_activate_user'} or {@see 'wpmu_activate_blog'} for events 
  909. * that should happen only when users or sites are self-created (since 
  910. * those actions are not called when users and sites are created 
  911. * by a Super Admin). 
  912. * 
  913. * @since MU 
  914. * 
  915. * @global wpdb $wpdb WordPress database abstraction object. 
  916. * 
  917. * @param string $key The activation key provided to the user. 
  918. * @return array|WP_Error An array containing information about the activated user and/or blog 
  919. */ 
  920. function wpmu_activate_signup($key) { 
  921. global $wpdb; 
  922.  
  923. $signup = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->signups WHERE activation_key = %s", $key) ); 
  924.  
  925. if ( empty( $signup ) ) 
  926. return new WP_Error( 'invalid_key', __( 'Invalid activation key.' ) ); 
  927.  
  928. if ( $signup->active ) { 
  929. if ( empty( $signup->domain ) ) 
  930. return new WP_Error( 'already_active', __( 'The user is already active.' ), $signup ); 
  931. else 
  932. return new WP_Error( 'already_active', __( 'The site is already active.' ), $signup ); 
  933.  
  934. $meta = maybe_unserialize($signup->meta); 
  935. $password = wp_generate_password( 12, false ); 
  936.  
  937. $user_id = username_exists($signup->user_login); 
  938.  
  939. if ( ! $user_id ) 
  940. $user_id = wpmu_create_user($signup->user_login, $password, $signup->user_email); 
  941. else 
  942. $user_already_exists = true; 
  943.  
  944. if ( ! $user_id ) 
  945. return new WP_Error('create_user', __('Could not create user'), $signup); 
  946.  
  947. $now = current_time('mysql', true); 
  948.  
  949. if ( empty($signup->domain) ) { 
  950. $wpdb->update( $wpdb->signups, array('active' => 1, 'activated' => $now), array('activation_key' => $key) ); 
  951.  
  952. if ( isset( $user_already_exists ) ) 
  953. return new WP_Error( 'user_already_exists', __( 'That username is already activated.' ), $signup); 
  954.  
  955. /** 
  956. * Fires immediately after a new user is activated. 
  957. * 
  958. * @since MU 
  959. * 
  960. * @param int $user_id User ID. 
  961. * @param int $password User password. 
  962. * @param array $meta Signup meta data. 
  963. */ 
  964. do_action( 'wpmu_activate_user', $user_id, $password, $meta ); 
  965. return array( 'user_id' => $user_id, 'password' => $password, 'meta' => $meta ); 
  966.  
  967. $blog_id = wpmu_create_blog( $signup->domain, $signup->path, $signup->title, $user_id, $meta, $wpdb->siteid ); 
  968.  
  969. // TODO: What to do if we create a user but cannot create a blog? 
  970. if ( is_wp_error($blog_id) ) { 
  971. // If blog is taken, that means a previous attempt to activate this blog failed in between creating the blog and 
  972. // setting the activation flag. Let's just set the active flag and instruct the user to reset their password. 
  973. if ( 'blog_taken' == $blog_id->get_error_code() ) { 
  974. $blog_id->add_data( $signup ); 
  975. $wpdb->update( $wpdb->signups, array( 'active' => 1, 'activated' => $now ), array( 'activation_key' => $key ) ); 
  976. return $blog_id; 
  977.  
  978. $wpdb->update( $wpdb->signups, array('active' => 1, 'activated' => $now), array('activation_key' => $key) ); 
  979. /** 
  980. * Fires immediately after a site is activated. 
  981. * 
  982. * @since MU 
  983. * 
  984. * @param int $blog_id Blog ID. 
  985. * @param int $user_id User ID. 
  986. * @param int $password User password. 
  987. * @param string $signup_title Site title. 
  988. * @param array $meta Signup meta data. 
  989. */ 
  990. do_action( 'wpmu_activate_blog', $blog_id, $user_id, $password, $signup->title, $meta ); 
  991.  
  992. return array('blog_id' => $blog_id, 'user_id' => $user_id, 'password' => $password, 'title' => $signup->title, 'meta' => $meta); 
  993.  
  994. /** 
  995. * Create a user. 
  996. * 
  997. * This function runs when a user self-registers as well as when 
  998. * a Super Admin creates a new user. Hook to {@see 'wpmu_new_user'} for events 
  999. * that should affect all new users, but only on Multisite (otherwise 
  1000. * use {@see'user_register'}). 
  1001. * 
  1002. * @since MU 
  1003. * 
  1004. * @param string $user_name The new user's login name. 
  1005. * @param string $password The new user's password. 
  1006. * @param string $email The new user's email address. 
  1007. * @return int|false Returns false on failure, or int $user_id on success 
  1008. */ 
  1009. function wpmu_create_user( $user_name, $password, $email ) { 
  1010. $user_name = preg_replace( '/\s+/', '', sanitize_user( $user_name, true ) ); 
  1011.  
  1012. $user_id = wp_create_user( $user_name, $password, $email ); 
  1013. if ( is_wp_error( $user_id ) ) 
  1014. return false; 
  1015.  
  1016. // Newly created users have no roles or caps until they are added to a blog. 
  1017. delete_user_option( $user_id, 'capabilities' ); 
  1018. delete_user_option( $user_id, 'user_level' ); 
  1019.  
  1020. /** 
  1021. * Fires immediately after a new user is created. 
  1022. * 
  1023. * @since MU 
  1024. * 
  1025. * @param int $user_id User ID. 
  1026. */ 
  1027. do_action( 'wpmu_new_user', $user_id ); 
  1028.  
  1029. return $user_id; 
  1030.  
  1031. /** 
  1032. * Create a site. 
  1033. * 
  1034. * This function runs when a user self-registers a new site as well 
  1035. * as when a Super Admin creates a new site. Hook to {@see 'wpmu_new_blog'} 
  1036. * for events that should affect all new sites. 
  1037. * 
  1038. * On subdirectory installs, $domain is the same as the main site's 
  1039. * domain, and the path is the subdirectory name (eg 'example.com' 
  1040. * and '/blog1/'). On subdomain installs, $domain is the new subdomain + 
  1041. * root domain (eg 'blog1.example.com'), and $path is '/'. 
  1042. * 
  1043. * @since MU 
  1044. * 
  1045. * @param string $domain The new site's domain. 
  1046. * @param string $path The new site's path. 
  1047. * @param string $title The new site's title. 
  1048. * @param int $user_id The user ID of the new site's admin. 
  1049. * @param array $meta Optional. Used to set initial site options. 
  1050. * @param int $site_id Optional. Only relevant on multi-network installs. 
  1051. * @return int|WP_Error Returns WP_Error object on failure, int $blog_id on success 
  1052. */ 
  1053. function wpmu_create_blog( $domain, $path, $title, $user_id, $meta = array(), $site_id = 1 ) { 
  1054. $defaults = array( 
  1055. 'public' => 0,  
  1056. 'WPLANG' => get_site_option( 'WPLANG' ),  
  1057. ); 
  1058. $meta = wp_parse_args( $meta, $defaults ); 
  1059.  
  1060. $domain = preg_replace( '/\s+/', '', sanitize_user( $domain, true ) ); 
  1061.  
  1062. if ( is_subdomain_install() ) 
  1063. $domain = str_replace( '@', '', $domain ); 
  1064.  
  1065. $title = strip_tags( $title ); 
  1066. $user_id = (int) $user_id; 
  1067.  
  1068. if ( empty($path) ) 
  1069. $path = '/'; 
  1070.  
  1071. // Check if the domain has been used already. We should return an error message. 
  1072. if ( domain_exists($domain, $path, $site_id) ) 
  1073. return new WP_Error( 'blog_taken', __( 'Sorry, that site already exists!' ) ); 
  1074.  
  1075. if ( ! wp_installing() ) { 
  1076. wp_installing( true ); 
  1077.  
  1078. if ( ! $blog_id = insert_blog($domain, $path, $site_id) ) 
  1079. return new WP_Error('insert_blog', __('Could not create site.')); 
  1080.  
  1081. switch_to_blog($blog_id); 
  1082. install_blog($blog_id, $title); 
  1083. wp_install_defaults($user_id); 
  1084.  
  1085. add_user_to_blog($blog_id, $user_id, 'administrator'); 
  1086.  
  1087. foreach ( $meta as $key => $value ) { 
  1088. if ( in_array( $key, array( 'public', 'archived', 'mature', 'spam', 'deleted', 'lang_id' ) ) ) 
  1089. update_blog_status( $blog_id, $key, $value ); 
  1090. else 
  1091. update_option( $key, $value ); 
  1092.  
  1093. update_option( 'blog_public', (int) $meta['public'] ); 
  1094.  
  1095. if ( ! is_super_admin( $user_id ) && ! get_user_meta( $user_id, 'primary_blog', true ) ) 
  1096. update_user_meta( $user_id, 'primary_blog', $blog_id ); 
  1097.  
  1098. restore_current_blog(); 
  1099. /** 
  1100. * Fires immediately after a new site is created. 
  1101. * 
  1102. * @since MU 
  1103. * 
  1104. * @param int $blog_id Blog ID. 
  1105. * @param int $user_id User ID. 
  1106. * @param string $domain Site domain. 
  1107. * @param string $path Site path. 
  1108. * @param int $site_id Site ID. Only relevant on multi-network installs. 
  1109. * @param array $meta Meta data. Used to set initial site options. 
  1110. */ 
  1111. do_action( 'wpmu_new_blog', $blog_id, $user_id, $domain, $path, $site_id, $meta ); 
  1112.  
  1113. wp_cache_set( 'last_changed', microtime(), 'sites' ); 
  1114.  
  1115. return $blog_id; 
  1116.  
  1117. /** 
  1118. * Notifies the network admin that a new site has been activated. 
  1119. * 
  1120. * Filter {@see 'newblog_notify_siteadmin'} to change the content of 
  1121. * the notification email. 
  1122. * 
  1123. * @since MU 
  1124. * 
  1125. * @param int $blog_id The new site's ID. 
  1126. * @param string $deprecated Not used. 
  1127. * @return bool 
  1128. */ 
  1129. function newblog_notify_siteadmin( $blog_id, $deprecated = '' ) { 
  1130. if ( get_site_option( 'registrationnotification' ) != 'yes' ) 
  1131. return false; 
  1132.  
  1133. $email = get_site_option( 'admin_email' ); 
  1134. if ( is_email($email) == false ) 
  1135. return false; 
  1136.  
  1137. $options_site_url = esc_url(network_admin_url('settings.php')); 
  1138.  
  1139. switch_to_blog( $blog_id ); 
  1140. $blogname = get_option( 'blogname' ); 
  1141. $siteurl = site_url(); 
  1142. restore_current_blog(); 
  1143.  
  1144. /** translators: New site notification email. 1: Site URL, 2: User IP address, 3: Settings screen URL */ 
  1145. $msg = sprintf( __( 'New Site: %1$s 
  1146. URL: %2$s 
  1147. Remote IP: %3$s 
  1148.  
  1149. Disable these notifications: %4$s' ), $blogname, $siteurl, wp_unslash( $_SERVER['REMOTE_ADDR'] ), $options_site_url); 
  1150. /** 
  1151. * Filters the message body of the new site activation email sent 
  1152. * to the network administrator. 
  1153. * 
  1154. * @since MU 
  1155. * 
  1156. * @param string $msg Email body. 
  1157. */ 
  1158. $msg = apply_filters( 'newblog_notify_siteadmin', $msg ); 
  1159.  
  1160. wp_mail( $email, sprintf( __( 'New Site Registration: %s' ), $siteurl ), $msg ); 
  1161. return true; 
  1162.  
  1163. /** 
  1164. * Notifies the network admin that a new user has been activated. 
  1165. * 
  1166. * Filter {@see 'newuser_notify_siteadmin'} to change the content of 
  1167. * the notification email. 
  1168. * 
  1169. * @since MU 
  1170. * 
  1171. * @param int $user_id The new user's ID. 
  1172. * @return bool 
  1173. */ 
  1174. function newuser_notify_siteadmin( $user_id ) { 
  1175. if ( get_site_option( 'registrationnotification' ) != 'yes' ) 
  1176. return false; 
  1177.  
  1178. $email = get_site_option( 'admin_email' ); 
  1179.  
  1180. if ( is_email($email) == false ) 
  1181. return false; 
  1182.  
  1183. $user = get_userdata( $user_id ); 
  1184.  
  1185. $options_site_url = esc_url(network_admin_url('settings.php')); 
  1186. /** translators: New user notification email. 1: User login, 2: User IP address, 3: Settings screen URL */ 
  1187. $msg = sprintf(__('New User: %1$s 
  1188. Remote IP: %2$s 
  1189.  
  1190. Disable these notifications: %3$s'), $user->user_login, wp_unslash( $_SERVER['REMOTE_ADDR'] ), $options_site_url); 
  1191.  
  1192. /** 
  1193. * Filters the message body of the new user activation email sent 
  1194. * to the network administrator. 
  1195. * 
  1196. * @since MU 
  1197. * 
  1198. * @param string $msg Email body. 
  1199. * @param WP_User $user WP_User instance of the new user. 
  1200. */ 
  1201. $msg = apply_filters( 'newuser_notify_siteadmin', $msg, $user ); 
  1202. wp_mail( $email, sprintf(__('New User Registration: %s'), $user->user_login), $msg ); 
  1203. return true; 
  1204.  
  1205. /** 
  1206. * Check whether a blogname is already taken. 
  1207. * 
  1208. * Used during the new site registration process to ensure 
  1209. * that each blogname is unique. 
  1210. * 
  1211. * @since MU 
  1212. * 
  1213. * @global wpdb $wpdb WordPress database abstraction object. 
  1214. * 
  1215. * @param string $domain The domain to be checked. 
  1216. * @param string $path The path to be checked. 
  1217. * @param int $site_id Optional. Relevant only on multi-network installs. 
  1218. * @return int 
  1219. */ 
  1220. function domain_exists($domain, $path, $site_id = 1) { 
  1221. $path = trailingslashit( $path ); 
  1222. $args = array( 
  1223. 'network_id' => $site_id,  
  1224. 'domain' => $domain,  
  1225. 'path' => $path,  
  1226. 'fields' => 'ids',  
  1227. ); 
  1228. $result = get_sites( $args ); 
  1229. $result = array_shift( $result ); 
  1230.  
  1231. /** 
  1232. * Filters whether a blogname is taken. 
  1233. * 
  1234. * @since 3.5.0 
  1235. * 
  1236. * @param int|null $result The blog_id if the blogname exists, null otherwise. 
  1237. * @param string $domain Domain to be checked. 
  1238. * @param string $path Path to be checked. 
  1239. * @param int $site_id Site ID. Relevant only on multi-network installs. 
  1240. */ 
  1241. return apply_filters( 'domain_exists', $result, $domain, $path, $site_id ); 
  1242.  
  1243. /** 
  1244. * Store basic site info in the blogs table. 
  1245. * 
  1246. * This function creates a row in the wp_blogs table and returns 
  1247. * the new blog's ID. It is the first step in creating a new blog. 
  1248. * 
  1249. * @since MU 
  1250. * 
  1251. * @global wpdb $wpdb WordPress database abstraction object. 
  1252. * 
  1253. * @param string $domain The domain of the new site. 
  1254. * @param string $path The path of the new site. 
  1255. * @param int $site_id Unless you're running a multi-network install, be sure to set this value to 1. 
  1256. * @return int|false The ID of the new row 
  1257. */ 
  1258. function insert_blog($domain, $path, $site_id) { 
  1259. global $wpdb; 
  1260.  
  1261. $path = trailingslashit($path); 
  1262. $site_id = (int) $site_id; 
  1263.  
  1264. $result = $wpdb->insert( $wpdb->blogs, array('site_id' => $site_id, 'domain' => $domain, 'path' => $path, 'registered' => current_time('mysql')) ); 
  1265. if ( ! $result ) 
  1266. return false; 
  1267.  
  1268. $blog_id = $wpdb->insert_id; 
  1269. refresh_blog_details( $blog_id ); 
  1270.  
  1271. wp_maybe_update_network_site_counts(); 
  1272.  
  1273. return $blog_id; 
  1274.  
  1275. /** 
  1276. * Install an empty blog. 
  1277. * 
  1278. * Creates the new blog tables and options. If calling this function 
  1279. * directly, be sure to use switch_to_blog() first, so that $wpdb 
  1280. * points to the new blog. 
  1281. * 
  1282. * @since MU 
  1283. * 
  1284. * @global wpdb $wpdb 
  1285. * @global WP_Roles $wp_roles 
  1286. * 
  1287. * @param int $blog_id The value returned by insert_blog(). 
  1288. * @param string $blog_title The title of the new site. 
  1289. */ 
  1290. function install_blog( $blog_id, $blog_title = '' ) { 
  1291. global $wpdb, $wp_roles; 
  1292.  
  1293. // Cast for security 
  1294. $blog_id = (int) $blog_id; 
  1295.  
  1296. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 
  1297.  
  1298. $suppress = $wpdb->suppress_errors(); 
  1299. if ( $wpdb->get_results( "DESCRIBE {$wpdb->posts}" ) ) 
  1300. die( '<h1>' . __( 'Already Installed' ) . '</h1><p>' . __( 'You appear to have already installed WordPress. To reinstall please clear your old database tables first.' ) . '</p></body></html>' ); 
  1301. $wpdb->suppress_errors( $suppress ); 
  1302.  
  1303. $url = get_blogaddress_by_id( $blog_id ); 
  1304.  
  1305. // Set everything up 
  1306. make_db_current_silent( 'blog' ); 
  1307. populate_options(); 
  1308. populate_roles(); 
  1309.  
  1310. // populate_roles() clears previous role definitions so we start over. 
  1311. $wp_roles = new WP_Roles(); 
  1312.  
  1313. $siteurl = $home = untrailingslashit( $url ); 
  1314.  
  1315. if ( ! is_subdomain_install() ) { 
  1316.  
  1317. if ( 'https' === parse_url( get_site_option( 'siteurl' ), PHP_URL_SCHEME ) ) { 
  1318. $siteurl = set_url_scheme( $siteurl, 'https' ); 
  1319. if ( 'https' === parse_url( get_home_url( get_network()->site_id ), PHP_URL_SCHEME ) ) { 
  1320. $home = set_url_scheme( $home, 'https' ); 
  1321.  
  1322.  
  1323. update_option( 'siteurl', $siteurl ); 
  1324. update_option( 'home', $home ); 
  1325.  
  1326. if ( get_site_option( 'ms_files_rewriting' ) ) 
  1327. update_option( 'upload_path', UPLOADBLOGSDIR . "/$blog_id/files" ); 
  1328. else 
  1329. update_option( 'upload_path', get_blog_option( get_network()->site_id, 'upload_path' ) ); 
  1330.  
  1331. update_option( 'blogname', wp_unslash( $blog_title ) ); 
  1332. update_option( 'admin_email', '' ); 
  1333.  
  1334. // remove all perms 
  1335. $table_prefix = $wpdb->get_blog_prefix(); 
  1336. delete_metadata( 'user', 0, $table_prefix . 'user_level', null, true ); // delete all 
  1337. delete_metadata( 'user', 0, $table_prefix . 'capabilities', null, true ); // delete all 
  1338.  
  1339. /** 
  1340. * Set blog defaults. 
  1341. * 
  1342. * This function creates a row in the wp_blogs table. 
  1343. * 
  1344. * @since MU 
  1345. * @deprecated MU 
  1346. * @deprecated Use wp_install_defaults() 
  1347. * 
  1348. * @global wpdb $wpdb WordPress database abstraction object. 
  1349. * 
  1350. * @param int $blog_id Ignored in this function. 
  1351. * @param int $user_id 
  1352. */ 
  1353. function install_blog_defaults($blog_id, $user_id) { 
  1354. global $wpdb; 
  1355.  
  1356. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); 
  1357.  
  1358. $suppress = $wpdb->suppress_errors(); 
  1359.  
  1360. wp_install_defaults($user_id); 
  1361.  
  1362. $wpdb->suppress_errors( $suppress ); 
  1363.  
  1364. /** 
  1365. * Notify a user that their blog activation has been successful. 
  1366. * 
  1367. * Filter {@see 'wpmu_welcome_notification'} to disable or bypass. 
  1368. * 
  1369. * Filter {@see 'update_welcome_email'} and {@see 'update_welcome_subject'} to 
  1370. * modify the content and subject line of the notification email. 
  1371. * 
  1372. * @since MU 
  1373. * 
  1374. * @param int $blog_id 
  1375. * @param int $user_id 
  1376. * @param string $password 
  1377. * @param string $title The new blog's title 
  1378. * @param array $meta Optional. Not used in the default function, but is passed along to hooks for customization. 
  1379. * @return bool 
  1380. */ 
  1381. function wpmu_welcome_notification( $blog_id, $user_id, $password, $title, $meta = array() ) { 
  1382. $current_network = get_network(); 
  1383.  
  1384. /** 
  1385. * Filters whether to bypass the welcome email after site activation. 
  1386. * 
  1387. * Returning false disables the welcome email. 
  1388. * 
  1389. * @since MU 
  1390. * 
  1391. * @param int|bool $blog_id Blog ID. 
  1392. * @param int $user_id User ID. 
  1393. * @param string $password User password. 
  1394. * @param string $title Site title. 
  1395. * @param array $meta Signup meta data. 
  1396. */ 
  1397. if ( ! apply_filters( 'wpmu_welcome_notification', $blog_id, $user_id, $password, $title, $meta ) ) 
  1398. return false; 
  1399.  
  1400. $user = get_userdata( $user_id ); 
  1401.  
  1402. $switched_locale = switch_to_locale( get_user_locale( $user ) ); 
  1403.  
  1404. $welcome_email = get_site_option( 'welcome_email' ); 
  1405. if ( $welcome_email == false ) { 
  1406. /** translators: Do not translate USERNAME, SITE_NAME, BLOG_URL, PASSWORD: those are placeholders. */ 
  1407. $welcome_email = __( 'Howdy USERNAME,  
  1408.  
  1409. Your new SITE_NAME site has been successfully set up at: 
  1410. BLOG_URL 
  1411.  
  1412. You can log in to the administrator account with the following information: 
  1413.  
  1414. Username: USERNAME 
  1415. Password: PASSWORD 
  1416. Log in here: BLOG_URLwp-login.php 
  1417.  
  1418. We hope you enjoy your new site. Thanks! 
  1419.  
  1420. --The Team @ SITE_NAME' ); 
  1421.  
  1422. $url = get_blogaddress_by_id($blog_id); 
  1423.  
  1424. $welcome_email = str_replace( 'SITE_NAME', $current_network->site_name, $welcome_email ); 
  1425. $welcome_email = str_replace( 'BLOG_TITLE', $title, $welcome_email ); 
  1426. $welcome_email = str_replace( 'BLOG_URL', $url, $welcome_email ); 
  1427. $welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email ); 
  1428. $welcome_email = str_replace( 'PASSWORD', $password, $welcome_email ); 
  1429.  
  1430. /** 
  1431. * Filters the content of the welcome email after site activation. 
  1432. * 
  1433. * Content should be formatted for transmission via wp_mail(). 
  1434. * 
  1435. * @since MU 
  1436. * 
  1437. * @param string $welcome_email Message body of the email. 
  1438. * @param int $blog_id Blog ID. 
  1439. * @param int $user_id User ID. 
  1440. * @param string $password User password. 
  1441. * @param string $title Site title. 
  1442. * @param array $meta Signup meta data. 
  1443. */ 
  1444. $welcome_email = apply_filters( 'update_welcome_email', $welcome_email, $blog_id, $user_id, $password, $title, $meta ); 
  1445. $admin_email = get_site_option( 'admin_email' ); 
  1446.  
  1447. if ( $admin_email == '' ) 
  1448. $admin_email = 'support@' . $_SERVER['SERVER_NAME']; 
  1449.  
  1450. $from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) ); 
  1451. $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; 
  1452. $message = $welcome_email; 
  1453.  
  1454. if ( empty( $current_network->site_name ) ) 
  1455. $current_network->site_name = 'WordPress'; 
  1456.  
  1457. /** translators: New site notification email subject. 1: Network name, 2: New site name */ 
  1458. $subject = __( 'New %1$s Site: %2$s' ); 
  1459.  
  1460. /** 
  1461. * Filters the subject of the welcome email after site activation. 
  1462. * 
  1463. * @since MU 
  1464. * 
  1465. * @param string $subject Subject of the email. 
  1466. */ 
  1467. $subject = apply_filters( 'update_welcome_subject', sprintf( $subject, $current_network->site_name, wp_unslash( $title ) ) ); 
  1468. wp_mail( $user->user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 
  1469.  
  1470. if ( $switched_locale ) { 
  1471. restore_previous_locale(); 
  1472.  
  1473. return true; 
  1474.  
  1475. /** 
  1476. * Notify a user that their account activation has been successful. 
  1477. * 
  1478. * Filter {@see 'wpmu_welcome_user_notification'} to disable or bypass. 
  1479. * 
  1480. * Filter {@see 'update_welcome_user_email'} and {@see 'update_welcome_user_subject'} to 
  1481. * modify the content and subject line of the notification email. 
  1482. * 
  1483. * @since MU 
  1484. * 
  1485. * @param int $user_id 
  1486. * @param string $password 
  1487. * @param array $meta Optional. Not used in the default function, but is passed along to hooks for customization. 
  1488. * @return bool 
  1489. */ 
  1490. function wpmu_welcome_user_notification( $user_id, $password, $meta = array() ) { 
  1491. $current_network = get_network(); 
  1492.  
  1493. /** 
  1494. * Filters whether to bypass the welcome email after user activation. 
  1495. * 
  1496. * Returning false disables the welcome email. 
  1497. * 
  1498. * @since MU 
  1499. * 
  1500. * @param int $user_id User ID. 
  1501. * @param string $password User password. 
  1502. * @param array $meta Signup meta data. 
  1503. */ 
  1504. if ( ! apply_filters( 'wpmu_welcome_user_notification', $user_id, $password, $meta ) ) 
  1505. return false; 
  1506.  
  1507. $welcome_email = get_site_option( 'welcome_user_email' ); 
  1508.  
  1509. $user = get_userdata( $user_id ); 
  1510.  
  1511. $switched_locale = switch_to_locale( get_user_locale( $user ) ); 
  1512.  
  1513. /** 
  1514. * Filters the content of the welcome email after user activation. 
  1515. * 
  1516. * Content should be formatted for transmission via wp_mail(). 
  1517. * 
  1518. * @since MU 
  1519. * 
  1520. * @param string $welcome_email The message body of the account activation success email. 
  1521. * @param int $user_id User ID. 
  1522. * @param string $password User password. 
  1523. * @param array $meta Signup meta data. 
  1524. */ 
  1525. $welcome_email = apply_filters( 'update_welcome_user_email', $welcome_email, $user_id, $password, $meta ); 
  1526. $welcome_email = str_replace( 'SITE_NAME', $current_network->site_name, $welcome_email ); 
  1527. $welcome_email = str_replace( 'USERNAME', $user->user_login, $welcome_email ); 
  1528. $welcome_email = str_replace( 'PASSWORD', $password, $welcome_email ); 
  1529. $welcome_email = str_replace( 'LOGINLINK', wp_login_url(), $welcome_email ); 
  1530.  
  1531. $admin_email = get_site_option( 'admin_email' ); 
  1532.  
  1533. if ( $admin_email == '' ) 
  1534. $admin_email = 'support@' . $_SERVER['SERVER_NAME']; 
  1535.  
  1536. $from_name = get_site_option( 'site_name' ) == '' ? 'WordPress' : esc_html( get_site_option( 'site_name' ) ); 
  1537. $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; 
  1538. $message = $welcome_email; 
  1539.  
  1540. if ( empty( $current_network->site_name ) ) 
  1541. $current_network->site_name = 'WordPress'; 
  1542.  
  1543. /** translators: New user notification email subject. 1: Network name, 2: New user login */ 
  1544. $subject = __( 'New %1$s User: %2$s' ); 
  1545.  
  1546. /** 
  1547. * Filters the subject of the welcome email after user activation. 
  1548. * 
  1549. * @since MU 
  1550. * 
  1551. * @param string $subject Subject of the email. 
  1552. */ 
  1553. $subject = apply_filters( 'update_welcome_user_subject', sprintf( $subject, $current_network->site_name, $user->user_login) ); 
  1554. wp_mail( $user->user_email, wp_specialchars_decode( $subject ), $message, $message_headers ); 
  1555.  
  1556. if ( $switched_locale ) { 
  1557. restore_previous_locale(); 
  1558.  
  1559. return true; 
  1560.  
  1561. /** 
  1562. * Get the current network. 
  1563. * 
  1564. * Returns an object containing the 'id', 'domain', 'path', and 'site_name' 
  1565. * properties of the network being viewed. 
  1566. * 
  1567. * @see wpmu_current_site() 
  1568. * 
  1569. * @since MU 
  1570. * 
  1571. * @global WP_Network $current_site 
  1572. * 
  1573. * @return WP_Network 
  1574. */ 
  1575. function get_current_site() { 
  1576. global $current_site; 
  1577. return $current_site; 
  1578.  
  1579. /** 
  1580. * Get a user's most recent post. 
  1581. * 
  1582. * Walks through each of a user's blogs to find the post with 
  1583. * the most recent post_date_gmt. 
  1584. * 
  1585. * @since MU 
  1586. * 
  1587. * @global wpdb $wpdb WordPress database abstraction object. 
  1588. * 
  1589. * @param int $user_id 
  1590. * @return array Contains the blog_id, post_id, post_date_gmt, and post_gmt_ts 
  1591. */ 
  1592. function get_most_recent_post_of_user( $user_id ) { 
  1593. global $wpdb; 
  1594.  
  1595. $user_blogs = get_blogs_of_user( (int) $user_id ); 
  1596. $most_recent_post = array(); 
  1597.  
  1598. // Walk through each blog and get the most recent post 
  1599. // published by $user_id 
  1600. foreach ( (array) $user_blogs as $blog ) { 
  1601. $prefix = $wpdb->get_blog_prefix( $blog->userblog_id ); 
  1602. $recent_post = $wpdb->get_row( $wpdb->prepare("SELECT ID, post_date_gmt FROM {$prefix}posts WHERE post_author = %d AND post_type = 'post' AND post_status = 'publish' ORDER BY post_date_gmt DESC LIMIT 1", $user_id ), ARRAY_A); 
  1603.  
  1604. // Make sure we found a post 
  1605. if ( isset($recent_post['ID']) ) { 
  1606. $post_gmt_ts = strtotime($recent_post['post_date_gmt']); 
  1607.  
  1608. // If this is the first post checked or if this post is 
  1609. // newer than the current recent post, make it the new 
  1610. // most recent post. 
  1611. if ( !isset($most_recent_post['post_gmt_ts']) || ( $post_gmt_ts > $most_recent_post['post_gmt_ts'] ) ) { 
  1612. $most_recent_post = array( 
  1613. 'blog_id' => $blog->userblog_id,  
  1614. 'post_id' => $recent_post['ID'],  
  1615. 'post_date_gmt' => $recent_post['post_date_gmt'],  
  1616. 'post_gmt_ts' => $post_gmt_ts 
  1617. ); 
  1618.  
  1619. return $most_recent_post; 
  1620.  
  1621. // Misc functions 
  1622.  
  1623. /** 
  1624. * Get the size of a directory. 
  1625. * 
  1626. * A helper function that is used primarily to check whether 
  1627. * a blog has exceeded its allowed upload space. 
  1628. * 
  1629. * @since MU 
  1630. * 
  1631. * @param string $directory Full path of a directory. 
  1632. * @return int Size of the directory in MB. 
  1633. */ 
  1634. function get_dirsize( $directory ) { 
  1635. $dirsize = get_transient( 'dirsize_cache' ); 
  1636. if ( is_array( $dirsize ) && isset( $dirsize[ $directory ][ 'size' ] ) ) 
  1637. return $dirsize[ $directory ][ 'size' ]; 
  1638.  
  1639. if ( ! is_array( $dirsize ) ) 
  1640. $dirsize = array(); 
  1641.  
  1642. // Exclude individual site directories from the total when checking the main site,  
  1643. // as they are subdirectories and should not be counted. 
  1644. if ( is_main_site() ) { 
  1645. $dirsize[ $directory ][ 'size' ] = recurse_dirsize( $directory, $directory . '/sites' ); 
  1646. } else { 
  1647. $dirsize[ $directory ][ 'size' ] = recurse_dirsize( $directory ); 
  1648.  
  1649. set_transient( 'dirsize_cache', $dirsize, HOUR_IN_SECONDS ); 
  1650. return $dirsize[ $directory ][ 'size' ]; 
  1651.  
  1652. /** 
  1653. * Get the size of a directory recursively. 
  1654. * 
  1655. * Used by get_dirsize() to get a directory's size when it contains 
  1656. * other directories. 
  1657. * 
  1658. * @since MU 
  1659. * @since 4.3.0 $exclude parameter added. 
  1660. * 
  1661. * @param string $directory Full path of a directory. 
  1662. * @param string $exclude Optional. Full path of a subdirectory to exclude from the total. 
  1663. * @return int|false Size in MB if a valid directory. False if not. 
  1664. */ 
  1665. function recurse_dirsize( $directory, $exclude = null ) { 
  1666. $size = 0; 
  1667.  
  1668. $directory = untrailingslashit( $directory ); 
  1669.  
  1670. if ( ! file_exists( $directory ) || ! is_dir( $directory ) || ! is_readable( $directory ) || $directory === $exclude ) { 
  1671. return false; 
  1672.  
  1673. if ($handle = opendir($directory)) { 
  1674. while(($file = readdir($handle)) !== false) { 
  1675. $path = $directory.'/'.$file; 
  1676. if ($file != '.' && $file != '..') { 
  1677. if (is_file($path)) { 
  1678. $size += filesize($path); 
  1679. } elseif (is_dir($path)) { 
  1680. $handlesize = recurse_dirsize( $path, $exclude ); 
  1681. if ($handlesize > 0) 
  1682. $size += $handlesize; 
  1683. closedir($handle); 
  1684. return $size; 
  1685.  
  1686. /** 
  1687. * Check an array of MIME types against a whitelist. 
  1688. * 
  1689. * WordPress ships with a set of allowed upload filetypes,  
  1690. * which is defined in wp-includes/functions.php in 
  1691. * get_allowed_mime_types(). This function is used to filter 
  1692. * that list against the filetype whitelist provided by Multisite 
  1693. * Super Admins at wp-admin/network/settings.php. 
  1694. * 
  1695. * @since MU 
  1696. * 
  1697. * @param array $mimes 
  1698. * @return array 
  1699. */ 
  1700. function check_upload_mimes( $mimes ) { 
  1701. $site_exts = explode( ' ', get_site_option( 'upload_filetypes', 'jpg jpeg png gif' ) ); 
  1702. $site_mimes = array(); 
  1703. foreach ( $site_exts as $ext ) { 
  1704. foreach ( $mimes as $ext_pattern => $mime ) { 
  1705. if ( $ext != '' && strpos( $ext_pattern, $ext ) !== false ) 
  1706. $site_mimes[$ext_pattern] = $mime; 
  1707. return $site_mimes; 
  1708.  
  1709. /** 
  1710. * Update a blog's post count. 
  1711. * 
  1712. * WordPress MS stores a blog's post count as an option so as 
  1713. * to avoid extraneous COUNTs when a blog's details are fetched 
  1714. * with get_site(). This function is called when posts are published 
  1715. * or unpublished to make sure the count stays current. 
  1716. * 
  1717. * @since MU 
  1718. * 
  1719. * @global wpdb $wpdb WordPress database abstraction object. 
  1720. * 
  1721. * @param string $deprecated Not used. 
  1722. */ 
  1723. function update_posts_count( $deprecated = '' ) { 
  1724. global $wpdb; 
  1725. update_option( 'post_count', (int) $wpdb->get_var( "SELECT COUNT(ID) FROM {$wpdb->posts} WHERE post_status = 'publish' and post_type = 'post'" ) ); 
  1726.  
  1727. /** 
  1728. * Logs user registrations. 
  1729. * 
  1730. * @since MU 
  1731. * 
  1732. * @global wpdb $wpdb WordPress database abstraction object. 
  1733. * 
  1734. * @param int $blog_id 
  1735. * @param int $user_id 
  1736. */ 
  1737. function wpmu_log_new_registrations( $blog_id, $user_id ) { 
  1738. global $wpdb; 
  1739. $user = get_userdata( (int) $user_id ); 
  1740. if ( $user ) 
  1741. $wpdb->insert( $wpdb->registration_log, array('email' => $user->user_email, 'IP' => preg_replace( '/[^0-9., ]/', '', wp_unslash( $_SERVER['REMOTE_ADDR'] ) ), 'blog_id' => $blog_id, 'date_registered' => current_time('mysql')) ); 
  1742.  
  1743. /** 
  1744. * Maintains a canonical list of terms by syncing terms created for each blog with the global terms table. 
  1745. * 
  1746. * @since 3.0.0 
  1747. * 
  1748. * @see term_id_filter 
  1749. * 
  1750. * @global wpdb $wpdb WordPress database abstraction object. 
  1751. * @staticvar int $global_terms_recurse 
  1752. * 
  1753. * @param int $term_id An ID for a term on the current blog. 
  1754. * @param string $deprecated Not used. 
  1755. * @return int An ID from the global terms table mapped from $term_id. 
  1756. */ 
  1757. function global_terms( $term_id, $deprecated = '' ) { 
  1758. global $wpdb; 
  1759. static $global_terms_recurse = null; 
  1760.  
  1761. if ( !global_terms_enabled() ) 
  1762. return $term_id; 
  1763.  
  1764. // prevent a race condition 
  1765. $recurse_start = false; 
  1766. if ( $global_terms_recurse === null ) { 
  1767. $recurse_start = true; 
  1768. $global_terms_recurse = 1; 
  1769. } elseif ( 10 < $global_terms_recurse++ ) { 
  1770. return $term_id; 
  1771.  
  1772. $term_id = intval( $term_id ); 
  1773. $c = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->terms WHERE term_id = %d", $term_id ) ); 
  1774.  
  1775. $global_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM $wpdb->sitecategories WHERE category_nicename = %s", $c->slug ) ); 
  1776. if ( $global_id == null ) { 
  1777. $used_global_id = $wpdb->get_var( $wpdb->prepare( "SELECT cat_ID FROM $wpdb->sitecategories WHERE cat_ID = %d", $c->term_id ) ); 
  1778. if ( null == $used_global_id ) { 
  1779. $wpdb->insert( $wpdb->sitecategories, array( 'cat_ID' => $term_id, 'cat_name' => $c->name, 'category_nicename' => $c->slug ) ); 
  1780. $global_id = $wpdb->insert_id; 
  1781. if ( empty( $global_id ) ) 
  1782. return $term_id; 
  1783. } else { 
  1784. $max_global_id = $wpdb->get_var( "SELECT MAX(cat_ID) FROM $wpdb->sitecategories" ); 
  1785. $max_local_id = $wpdb->get_var( "SELECT MAX(term_id) FROM $wpdb->terms" ); 
  1786. $new_global_id = max( $max_global_id, $max_local_id ) + mt_rand( 100, 400 ); 
  1787. $wpdb->insert( $wpdb->sitecategories, array( 'cat_ID' => $new_global_id, 'cat_name' => $c->name, 'category_nicename' => $c->slug ) ); 
  1788. $global_id = $wpdb->insert_id; 
  1789. } elseif ( $global_id != $term_id ) { 
  1790. $local_id = $wpdb->get_var( $wpdb->prepare( "SELECT term_id FROM $wpdb->terms WHERE term_id = %d", $global_id ) ); 
  1791. if ( null != $local_id ) { 
  1792. global_terms( $local_id ); 
  1793. if ( 10 < $global_terms_recurse ) { 
  1794. $global_id = $term_id; 
  1795.  
  1796. if ( $global_id != $term_id ) { 
  1797. if ( get_option( 'default_category' ) == $term_id ) 
  1798. update_option( 'default_category', $global_id ); 
  1799.  
  1800. $wpdb->update( $wpdb->terms, array('term_id' => $global_id), array('term_id' => $term_id) ); 
  1801. $wpdb->update( $wpdb->term_taxonomy, array('term_id' => $global_id), array('term_id' => $term_id) ); 
  1802. $wpdb->update( $wpdb->term_taxonomy, array('parent' => $global_id), array('parent' => $term_id) ); 
  1803.  
  1804. clean_term_cache($term_id); 
  1805. if ( $recurse_start ) 
  1806. $global_terms_recurse = null; 
  1807.  
  1808. return $global_id; 
  1809.  
  1810. /** 
  1811. * Ensure that the current site's domain is listed in the allowed redirect host list. 
  1812. * 
  1813. * @see wp_validate_redirect() 
  1814. * @since MU 
  1815. * 
  1816. * @param array|string $deprecated Not used. 
  1817. * @return array The current site's domain 
  1818. */ 
  1819. function redirect_this_site( $deprecated = '' ) { 
  1820. return array( get_network()->domain ); 
  1821.  
  1822. /** 
  1823. * Check whether an upload is too big. 
  1824. * 
  1825. * @since MU 
  1826. * 
  1827. * @blessed 
  1828. * 
  1829. * @param array $upload 
  1830. * @return string|array If the upload is under the size limit, $upload is returned. Otherwise returns an error message. 
  1831. */ 
  1832. function upload_is_file_too_big( $upload ) { 
  1833. if ( ! is_array( $upload ) || defined( 'WP_IMPORTING' ) || get_site_option( 'upload_space_check_disabled' ) ) 
  1834. return $upload; 
  1835.  
  1836. if ( strlen( $upload['bits'] ) > ( KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ) ) ) { 
  1837. return sprintf( __( 'This file is too big. Files must be less than %d KB in size.' ) . '<br />', get_site_option( 'fileupload_maxk', 1500 ) ); 
  1838.  
  1839. return $upload; 
  1840.  
  1841. /** 
  1842. * Add a nonce field to the signup page. 
  1843. * 
  1844. * @since MU 
  1845. */ 
  1846. function signup_nonce_fields() { 
  1847. $id = mt_rand(); 
  1848. echo "<input type='hidden' name='signup_form_id' value='{$id}' />"; 
  1849. wp_nonce_field('signup_form_' . $id, '_signup_form', false); 
  1850.  
  1851. /** 
  1852. * Process the signup nonce created in signup_nonce_fields(). 
  1853. * 
  1854. * @since MU 
  1855. * 
  1856. * @param array $result 
  1857. * @return array 
  1858. */ 
  1859. function signup_nonce_check( $result ) { 
  1860. if ( !strpos( $_SERVER[ 'PHP_SELF' ], 'wp-signup.php' ) ) 
  1861. return $result; 
  1862.  
  1863. if ( wp_create_nonce('signup_form_' . $_POST[ 'signup_form_id' ]) != $_POST['_signup_form'] ) 
  1864. wp_die( __( 'Please try again.' ) ); 
  1865.  
  1866. return $result; 
  1867.  
  1868. /** 
  1869. * Correct 404 redirects when NOBLOGREDIRECT is defined. 
  1870. * 
  1871. * @since MU 
  1872. */ 
  1873. function maybe_redirect_404() { 
  1874. /** 
  1875. * Filters the redirect URL for 404s on the main site. 
  1876. * 
  1877. * The filter is only evaluated if the NOBLOGREDIRECT constant is defined. 
  1878. * 
  1879. * @since 3.0.0 
  1880. * 
  1881. * @param string $no_blog_redirect The redirect URL defined in NOBLOGREDIRECT. 
  1882. */ 
  1883. if ( is_main_site() && is_404() && defined( 'NOBLOGREDIRECT' ) && ( $destination = apply_filters( 'blog_redirect_404', NOBLOGREDIRECT ) ) ) { 
  1884. if ( $destination == '%siteurl%' ) 
  1885. $destination = network_home_url(); 
  1886. wp_redirect( $destination ); 
  1887. exit(); 
  1888.  
  1889. /** 
  1890. * Add a new user to a blog by visiting /newbloguser/username/. 
  1891. * 
  1892. * This will only work when the user's details are saved as an option 
  1893. * keyed as 'new_user_x', where 'x' is the username of the user to be 
  1894. * added, as when a user is invited through the regular WP Add User interface. 
  1895. * 
  1896. * @since MU 
  1897. */ 
  1898. function maybe_add_existing_user_to_blog() { 
  1899. if ( false === strpos( $_SERVER[ 'REQUEST_URI' ], '/newbloguser/' ) ) 
  1900. return; 
  1901.  
  1902. $parts = explode( '/', $_SERVER[ 'REQUEST_URI' ] ); 
  1903. $key = array_pop( $parts ); 
  1904.  
  1905. if ( $key == '' ) 
  1906. $key = array_pop( $parts ); 
  1907.  
  1908. $details = get_option( 'new_user_' . $key ); 
  1909. if ( !empty( $details ) ) 
  1910. delete_option( 'new_user_' . $key ); 
  1911.  
  1912. if ( empty( $details ) || is_wp_error( add_existing_user_to_blog( $details ) ) ) 
  1913. wp_die( sprintf(__('An error occurred adding you to this site. Back to the <a href="%s">homepage</a>.'), home_url() ) ); 
  1914.  
  1915. wp_die( sprintf( __( 'You have been added to this site. Please visit the <a href="%s">homepage</a> or <a href="%s">log in</a> using your username and password.' ), home_url(), admin_url() ), __( 'WordPress › Success' ), array( 'response' => 200 ) ); 
  1916.  
  1917. /** 
  1918. * Add a user to a blog based on details from maybe_add_existing_user_to_blog(). 
  1919. * 
  1920. * @since MU 
  1921. * 
  1922. * @param array $details 
  1923. * @return true|WP_Error|void 
  1924. */ 
  1925. function add_existing_user_to_blog( $details = false ) { 
  1926. if ( is_array( $details ) ) { 
  1927. $blog_id = get_current_blog_id(); 
  1928. $result = add_user_to_blog( $blog_id, $details[ 'user_id' ], $details[ 'role' ] ); 
  1929. /** 
  1930. * Fires immediately after an existing user is added to a site. 
  1931. * 
  1932. * @since MU 
  1933. * 
  1934. * @param int $user_id User ID. 
  1935. * @param mixed $result True on success or a WP_Error object if the user doesn't exist. 
  1936. */ 
  1937. do_action( 'added_existing_user', $details['user_id'], $result ); 
  1938. return $result; 
  1939.  
  1940. /** 
  1941. * Adds a newly created user to the appropriate blog 
  1942. * 
  1943. * To add a user in general, use add_user_to_blog(). This function 
  1944. * is specifically hooked into the {@see 'wpmu_activate_user'} action. 
  1945. * 
  1946. * @since MU 
  1947. * @see add_user_to_blog() 
  1948. * 
  1949. * @param int $user_id 
  1950. * @param mixed $password Ignored. 
  1951. * @param array $meta 
  1952. */ 
  1953. function add_new_user_to_blog( $user_id, $password, $meta ) { 
  1954. if ( !empty( $meta[ 'add_to_blog' ] ) ) { 
  1955. $blog_id = $meta[ 'add_to_blog' ]; 
  1956. $role = $meta[ 'new_role' ]; 
  1957. remove_user_from_blog($user_id, get_network()->site_id); // remove user from main blog. 
  1958. add_user_to_blog( $blog_id, $user_id, $role ); 
  1959. update_user_meta( $user_id, 'primary_blog', $blog_id ); 
  1960.  
  1961. /** 
  1962. * Correct From host on outgoing mail to match the site domain 
  1963. * 
  1964. * @since MU 
  1965. * 
  1966. * @param PHPMailer $phpmailer The PHPMailer instance, passed by reference. 
  1967. */ 
  1968. function fix_phpmailer_messageid( $phpmailer ) { 
  1969. $phpmailer->Hostname = get_network()->domain; 
  1970.  
  1971. /** 
  1972. * Check to see whether a user is marked as a spammer, based on user login. 
  1973. * 
  1974. * @since MU 
  1975. * 
  1976. * @param string|WP_User $user Optional. Defaults to current user. WP_User object,  
  1977. * or user login name as a string. 
  1978. * @return bool 
  1979. */ 
  1980. function is_user_spammy( $user = null ) { 
  1981. if ( ! ( $user instanceof WP_User ) ) { 
  1982. if ( $user ) { 
  1983. $user = get_user_by( 'login', $user ); 
  1984. } else { 
  1985. $user = wp_get_current_user(); 
  1986.  
  1987. return $user && isset( $user->spam ) && 1 == $user->spam; 
  1988.  
  1989. /** 
  1990. * Update this blog's 'public' setting in the global blogs table. 
  1991. * 
  1992. * Public blogs have a setting of 1, private blogs are 0. 
  1993. * 
  1994. * @since MU 
  1995. * 
  1996. * @param int $old_value 
  1997. * @param int $value The new public value 
  1998. */ 
  1999. function update_blog_public( $old_value, $value ) { 
  2000. update_blog_status( get_current_blog_id(), 'public', (int) $value ); 
  2001.  
  2002. /** 
  2003. * Check whether a usermeta key has to do with the current blog. 
  2004. * 
  2005. * @since MU 
  2006. * 
  2007. * @global wpdb $wpdb WordPress database abstraction object. 
  2008. * 
  2009. * @param string $key 
  2010. * @param int $user_id Optional. Defaults to current user. 
  2011. * @param int $blog_id Optional. Defaults to current blog. 
  2012. * @return bool 
  2013. */ 
  2014. function is_user_option_local( $key, $user_id = 0, $blog_id = 0 ) { 
  2015. global $wpdb; 
  2016.  
  2017. $current_user = wp_get_current_user(); 
  2018. if ( $blog_id == 0 ) { 
  2019. $blog_id = $wpdb->blogid; 
  2020. $local_key = $wpdb->get_blog_prefix( $blog_id ) . $key; 
  2021.  
  2022. return isset( $current_user->$local_key ); 
  2023.  
  2024. /** 
  2025. * Check whether users can self-register, based on Network settings. 
  2026. * 
  2027. * @since MU 
  2028. * 
  2029. * @return bool 
  2030. */ 
  2031. function users_can_register_signup_filter() { 
  2032. $registration = get_site_option('registration'); 
  2033. return ( $registration == 'all' || $registration == 'user' ); 
  2034.  
  2035. /** 
  2036. * Ensure that the welcome message is not empty. Currently unused. 
  2037. * 
  2038. * @since MU 
  2039. * 
  2040. * @param string $text 
  2041. * @return string 
  2042. */ 
  2043. function welcome_user_msg_filter( $text ) { 
  2044. if ( !$text ) { 
  2045. remove_filter( 'site_option_welcome_user_email', 'welcome_user_msg_filter' ); 
  2046.  
  2047. /** translators: Do not translate USERNAME, PASSWORD, LOGINLINK, SITE_NAME: those are placeholders. */ 
  2048. $text = __( 'Howdy USERNAME,  
  2049.  
  2050. Your new account is set up. 
  2051.  
  2052. You can log in with the following information: 
  2053. Username: USERNAME 
  2054. Password: PASSWORD 
  2055. LOGINLINK 
  2056.  
  2057. Thanks! 
  2058.  
  2059. --The Team @ SITE_NAME' ); 
  2060. update_site_option( 'welcome_user_email', $text ); 
  2061. return $text; 
  2062.  
  2063. /** 
  2064. * Whether to force SSL on content. 
  2065. * 
  2066. * @since 2.8.5 
  2067. * 
  2068. * @staticvar bool $forced_content 
  2069. * 
  2070. * @param bool $force 
  2071. * @return bool True if forced, false if not forced. 
  2072. */ 
  2073. function force_ssl_content( $force = '' ) { 
  2074. static $forced_content = false; 
  2075.  
  2076. if ( '' != $force ) { 
  2077. $old_forced = $forced_content; 
  2078. $forced_content = $force; 
  2079. return $old_forced; 
  2080.  
  2081. return $forced_content; 
  2082.  
  2083. /** 
  2084. * Formats a URL to use https. 
  2085. * 
  2086. * Useful as a filter. 
  2087. * 
  2088. * @since 2.8.5 
  2089. * 
  2090. * @param string $url URL 
  2091. * @return string URL with https as the scheme 
  2092. */ 
  2093. function filter_SSL( $url ) { 
  2094. if ( ! is_string( $url ) ) 
  2095. return get_bloginfo( 'url' ); // Return home blog url with proper scheme 
  2096.  
  2097. if ( force_ssl_content() && is_ssl() ) 
  2098. $url = set_url_scheme( $url, 'https' ); 
  2099.  
  2100. return $url; 
  2101.  
  2102. /** 
  2103. * Schedule update of the network-wide counts for the current network. 
  2104. * 
  2105. * @since 3.1.0 
  2106. */ 
  2107. function wp_schedule_update_network_counts() { 
  2108. if ( !is_main_site() ) 
  2109. return; 
  2110.  
  2111. if ( ! wp_next_scheduled('update_network_counts') && ! wp_installing() ) 
  2112. wp_schedule_event(time(), 'twicedaily', 'update_network_counts'); 
  2113.  
  2114. /** 
  2115. * Update the network-wide counts for the current network. 
  2116. * 
  2117. * @since 3.1.0 
  2118. */ 
  2119. function wp_update_network_counts() { 
  2120. wp_update_network_user_counts(); 
  2121. wp_update_network_site_counts(); 
  2122.  
  2123. /** 
  2124. * Update the count of sites for the current network. 
  2125. * 
  2126. * If enabled through the {@see 'enable_live_network_counts'} filter, update the sites count 
  2127. * on a network when a site is created or its status is updated. 
  2128. * 
  2129. * @since 3.7.0 
  2130. */ 
  2131. function wp_maybe_update_network_site_counts() { 
  2132. $is_small_network = ! wp_is_large_network( 'sites' ); 
  2133.  
  2134. /** 
  2135. * Filters whether to update network site or user counts when a new site is created. 
  2136. * 
  2137. * @since 3.7.0 
  2138. * 
  2139. * @see wp_is_large_network() 
  2140. * 
  2141. * @param bool $small_network Whether the network is considered small. 
  2142. * @param string $context Context. Either 'users' or 'sites'. 
  2143. */ 
  2144. if ( ! apply_filters( 'enable_live_network_counts', $is_small_network, 'sites' ) ) 
  2145. return; 
  2146.  
  2147. wp_update_network_site_counts(); 
  2148.  
  2149. /** 
  2150. * Update the network-wide users count. 
  2151. * 
  2152. * If enabled through the {@see 'enable_live_network_counts'} filter, update the users count 
  2153. * on a network when a user is created or its status is updated. 
  2154. * 
  2155. * @since 3.7.0 
  2156. */ 
  2157. function wp_maybe_update_network_user_counts() { 
  2158. $is_small_network = ! wp_is_large_network( 'users' ); 
  2159.  
  2160. /** This filter is documented in wp-includes/ms-functions.php */ 
  2161. if ( ! apply_filters( 'enable_live_network_counts', $is_small_network, 'users' ) ) 
  2162. return; 
  2163.  
  2164. wp_update_network_user_counts(); 
  2165.  
  2166. /** 
  2167. * Update the network-wide site count. 
  2168. * 
  2169. * @since 3.7.0 
  2170. * 
  2171. * @global wpdb $wpdb WordPress database abstraction object. 
  2172. */ 
  2173. function wp_update_network_site_counts() { 
  2174. global $wpdb; 
  2175.  
  2176. $count = get_sites( array( 
  2177. 'network_id' => $wpdb->siteid,  
  2178. 'spam' => 0,  
  2179. 'deleted' => 0,  
  2180. 'archived' => 0,  
  2181. 'count' => true,  
  2182. ) ); 
  2183.  
  2184. update_site_option( 'blog_count', $count ); 
  2185.  
  2186. /** 
  2187. * Update the network-wide user count. 
  2188. * 
  2189. * @since 3.7.0 
  2190. * 
  2191. * @global wpdb $wpdb WordPress database abstraction object. 
  2192. */ 
  2193. function wp_update_network_user_counts() { 
  2194. global $wpdb; 
  2195.  
  2196. $count = $wpdb->get_var( "SELECT COUNT(ID) as c FROM $wpdb->users WHERE spam = '0' AND deleted = '0'" ); 
  2197. update_site_option( 'user_count', $count ); 
  2198.  
  2199. /** 
  2200. * Returns the space used by the current blog. 
  2201. * 
  2202. * @since 3.5.0 
  2203. * 
  2204. * @return int Used space in megabytes 
  2205. */ 
  2206. function get_space_used() { 
  2207. /** 
  2208. * Filters the amount of storage space used by the current site. 
  2209. * 
  2210. * @since 3.5.0 
  2211. * 
  2212. * @param int|bool $space_used The amount of used space, in megabytes. Default false. 
  2213. */ 
  2214. $space_used = apply_filters( 'pre_get_space_used', false ); 
  2215. if ( false === $space_used ) { 
  2216. $upload_dir = wp_upload_dir(); 
  2217. $space_used = get_dirsize( $upload_dir['basedir'] ) / MB_IN_BYTES; 
  2218.  
  2219. return $space_used; 
  2220.  
  2221. /** 
  2222. * Returns the upload quota for the current blog. 
  2223. * 
  2224. * @since MU 
  2225. * 
  2226. * @return int Quota in megabytes 
  2227. */ 
  2228. function get_space_allowed() { 
  2229. $space_allowed = get_option( 'blog_upload_space' ); 
  2230.  
  2231. if ( ! is_numeric( $space_allowed ) ) 
  2232. $space_allowed = get_site_option( 'blog_upload_space' ); 
  2233.  
  2234. if ( ! is_numeric( $space_allowed ) ) 
  2235. $space_allowed = 100; 
  2236.  
  2237. /** 
  2238. * Filters the upload quota for the current site. 
  2239. * 
  2240. * @since 3.7.0 
  2241. * 
  2242. * @param int $space_allowed Upload quota in megabytes for the current blog. 
  2243. */ 
  2244. return apply_filters( 'get_space_allowed', $space_allowed ); 
  2245.  
  2246. /** 
  2247. * Determines if there is any upload space left in the current blog's quota. 
  2248. * 
  2249. * @since 3.0.0 
  2250. * 
  2251. * @return int of upload space available in bytes 
  2252. */ 
  2253. function get_upload_space_available() { 
  2254. $allowed = get_space_allowed(); 
  2255. if ( $allowed < 0 ) { 
  2256. $allowed = 0; 
  2257. $space_allowed = $allowed * MB_IN_BYTES; 
  2258. if ( get_site_option( 'upload_space_check_disabled' ) ) 
  2259. return $space_allowed; 
  2260.  
  2261. $space_used = get_space_used() * MB_IN_BYTES; 
  2262.  
  2263. if ( ( $space_allowed - $space_used ) <= 0 ) 
  2264. return 0; 
  2265.  
  2266. return $space_allowed - $space_used; 
  2267.  
  2268. /** 
  2269. * Determines if there is any upload space left in the current blog's quota. 
  2270. * 
  2271. * @since 3.0.0 
  2272. * @return bool True if space is available, false otherwise. 
  2273. */ 
  2274. function is_upload_space_available() { 
  2275. if ( get_site_option( 'upload_space_check_disabled' ) ) 
  2276. return true; 
  2277.  
  2278. return (bool) get_upload_space_available(); 
  2279.  
  2280. /** 
  2281. * Filters the maximum upload file size allowed, in bytes. 
  2282. * 
  2283. * @since 3.0.0 
  2284. * 
  2285. * @param int $size Upload size limit in bytes. 
  2286. * @return int Upload size limit in bytes. 
  2287. */ 
  2288. function upload_size_limit_filter( $size ) { 
  2289. $fileupload_maxk = KB_IN_BYTES * get_site_option( 'fileupload_maxk', 1500 ); 
  2290. if ( get_site_option( 'upload_space_check_disabled' ) ) 
  2291. return min( $size, $fileupload_maxk ); 
  2292.  
  2293. return min( $size, $fileupload_maxk, get_upload_space_available() ); 
  2294.  
  2295. /** 
  2296. * Whether or not we have a large network. 
  2297. * 
  2298. * The default criteria for a large network is either more than 10, 000 users or more than 10, 000 sites. 
  2299. * Plugins can alter this criteria using the {@see 'wp_is_large_network'} filter. 
  2300. * 
  2301. * @since 3.3.0 
  2302. * @param string $using 'sites or 'users'. Default is 'sites'. 
  2303. * @return bool True if the network meets the criteria for large. False otherwise. 
  2304. */ 
  2305. function wp_is_large_network( $using = 'sites' ) { 
  2306. if ( 'users' == $using ) { 
  2307. $count = get_user_count(); 
  2308. /** 
  2309. * Filters whether the network is considered large. 
  2310. * 
  2311. * @since 3.3.0 
  2312. * 
  2313. * @param bool $is_large_network Whether the network has more than 10000 users or sites. 
  2314. * @param string $component The component to count. Accepts 'users', or 'sites'. 
  2315. * @param int $count The count of items for the component. 
  2316. */ 
  2317. return apply_filters( 'wp_is_large_network', $count > 10000, 'users', $count ); 
  2318.  
  2319. $count = get_blog_count(); 
  2320. /** This filter is documented in wp-includes/ms-functions.php */ 
  2321. return apply_filters( 'wp_is_large_network', $count > 10000, 'sites', $count ); 
  2322.  
  2323. /** 
  2324. * Retrieves a list of reserved site on a sub-directory Multisite install. 
  2325. * 
  2326. * @since 4.4.0 
  2327. * 
  2328. * @return array $names Array of reserved subdirectory names. 
  2329. */ 
  2330. function get_subdirectory_reserved_names() { 
  2331. $names = array( 
  2332. 'page', 'comments', 'blog', 'files', 'feed', 'wp-admin',  
  2333. 'wp-content', 'wp-includes', 'wp-json', 'embed' 
  2334. ); 
  2335.  
  2336. /** 
  2337. * Filters reserved site names on a sub-directory Multisite install. 
  2338. * 
  2339. * @since 3.0.0 
  2340. * @since 4.4.0 'wp-admin', 'wp-content', 'wp-includes', 'wp-json', and 'embed' were added 
  2341. * to the reserved names list. 
  2342. * 
  2343. * @param array $subdirectory_reserved_names Array of reserved names. 
  2344. */ 
  2345. return apply_filters( 'subdirectory_reserved_names', $names ); 
.