/bp-core/bp-core-avatars.php

  1. <?php 
  2. /** 
  3. * BuddyPress Avatars. 
  4. * 
  5. * @package BuddyPress 
  6. * @subpackage Core 
  7. * @since 1.0.0 
  8. */ 
  9.  
  10. // Exit if accessed directly. 
  11. defined( 'ABSPATH' ) || exit; 
  12.  
  13. /** 
  14. * Set up the constants we need for avatar support. 
  15. * 
  16. * @since 1.2.0 
  17. */ 
  18. function bp_core_set_avatar_constants() { 
  19.  
  20. $bp = buddypress(); 
  21.  
  22. if ( !defined( 'BP_AVATAR_THUMB_WIDTH' ) ) 
  23. define( 'BP_AVATAR_THUMB_WIDTH', 50 ); 
  24.  
  25. if ( !defined( 'BP_AVATAR_THUMB_HEIGHT' ) ) 
  26. define( 'BP_AVATAR_THUMB_HEIGHT', 50 ); 
  27.  
  28. if ( !defined( 'BP_AVATAR_FULL_WIDTH' ) ) 
  29. define( 'BP_AVATAR_FULL_WIDTH', 150 ); 
  30.  
  31. if ( !defined( 'BP_AVATAR_FULL_HEIGHT' ) ) 
  32. define( 'BP_AVATAR_FULL_HEIGHT', 150 ); 
  33.  
  34. if ( !defined( 'BP_AVATAR_ORIGINAL_MAX_WIDTH' ) ) 
  35. define( 'BP_AVATAR_ORIGINAL_MAX_WIDTH', 450 ); 
  36.  
  37. if ( !defined( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE' ) ) { 
  38. define( 'BP_AVATAR_ORIGINAL_MAX_FILESIZE', bp_attachments_get_max_upload_file_size( 'avatar' ) ); 
  39.  
  40. if ( ! defined( 'BP_SHOW_AVATARS' ) ) { 
  41. define( 'BP_SHOW_AVATARS', bp_get_option( 'show_avatars' ) ); 
  42. add_action( 'bp_init', 'bp_core_set_avatar_constants', 3 ); 
  43.  
  44. /** 
  45. * Set up global variables related to avatars. 
  46. * 
  47. * @since 1.5.0 
  48. */ 
  49. function bp_core_set_avatar_globals() { 
  50. $bp = buddypress(); 
  51.  
  52. $bp->avatar = new stdClass; 
  53. $bp->avatar->thumb = new stdClass; 
  54. $bp->avatar->full = new stdClass; 
  55.  
  56. // Dimensions. 
  57. $bp->avatar->thumb->width = BP_AVATAR_THUMB_WIDTH; 
  58. $bp->avatar->thumb->height = BP_AVATAR_THUMB_HEIGHT; 
  59. $bp->avatar->full->width = BP_AVATAR_FULL_WIDTH; 
  60. $bp->avatar->full->height = BP_AVATAR_FULL_HEIGHT; 
  61.  
  62. // Upload maximums. 
  63. $bp->avatar->original_max_width = BP_AVATAR_ORIGINAL_MAX_WIDTH; 
  64. $bp->avatar->original_max_filesize = BP_AVATAR_ORIGINAL_MAX_FILESIZE; 
  65.  
  66. // Defaults. 
  67. $bp->avatar->thumb->default = bp_core_avatar_default_thumb(); 
  68. $bp->avatar->full->default = bp_core_avatar_default(); 
  69.  
  70. // These have to be set on page load in order to avoid infinite filter loops at runtime. 
  71. $bp->avatar->upload_path = bp_core_avatar_upload_path(); 
  72. $bp->avatar->url = bp_core_avatar_url(); 
  73.  
  74. // Cache the root blog's show_avatars setting, to avoid unnecessary 
  75. // calls to switch_to_blog(). 
  76. $bp->avatar->show_avatars = (bool) BP_SHOW_AVATARS; 
  77.  
  78. // Backpat for pre-1.5. 
  79. if ( ! defined( 'BP_AVATAR_UPLOAD_PATH' ) ) 
  80. define( 'BP_AVATAR_UPLOAD_PATH', $bp->avatar->upload_path ); 
  81.  
  82. // Backpat for pre-1.5. 
  83. if ( ! defined( 'BP_AVATAR_URL' ) ) 
  84. define( 'BP_AVATAR_URL', $bp->avatar->url ); 
  85.  
  86. /** 
  87. * Fires at the end of the core avatar globals setup. 
  88. * 
  89. * @since 1.5.0 
  90. */ 
  91. do_action( 'bp_core_set_avatar_globals' ); 
  92. add_action( 'bp_setup_globals', 'bp_core_set_avatar_globals' ); 
  93.  
  94. /** 
  95. * Get an avatar for a BuddyPress object. 
  96. * 
  97. * Supports avatars for users, groups, and blogs by default, but can be 
  98. * extended to support custom components as well. 
  99. * 
  100. * This function gives precedence to locally-uploaded avatars. When a local 
  101. * avatar is not found, Gravatar is queried. To disable Gravatar fallbacks 
  102. * locally: 
  103. * add_filter( 'bp_core_fetch_avatar_no_grav', '__return_true' ); 
  104. * 
  105. * @since 1.1.0 
  106. * @since 2.4.0 Added 'extra_attr', 'scheme', 'rating' and 'force_default' for $args. 
  107. * These are inherited from WordPress 4.2.0. See {@link get_avatar()}. 
  108. * 
  109. * @param array|string $args { 
  110. * An array of arguments. All arguments are technically optional; some 
  111. * will, if not provided, be auto-detected by bp_core_fetch_avatar(). This 
  112. * auto-detection is described more below, when discussing specific 
  113. * arguments. 
  114. * 
  115. * @type int|bool $item_id The numeric ID of the item for which you're requesting 
  116. * an avatar (eg, a user ID). If no 'item_id' is present,  
  117. * the function attempts to infer an ID from the 'object' + the 
  118. * current context: if 'object' is 'user' and the current page is a 
  119. * user page, 'item_id' will default to the displayed user ID; if 
  120. * 'group' and on a group page, to the current group ID; if 'blog',  
  121. * to the current blog's ID. If no 'item_id' can be determined in 
  122. * this way, the function returns false. Default: false. 
  123. * @type string $object The kind of object for which you're getting an 
  124. * avatar. BuddyPress natively supports three options: 'user',  
  125. * 'group', 'blog'; a plugin may register more. Default: 'user'. 
  126. * @type string $type When a new avatar is uploaded to BP, 'thumb' and 
  127. * 'full' versions are saved. This parameter specifies whether you'd 
  128. * like the 'full' or smaller 'thumb' avatar. Default: 'thumb'. 
  129. * @type string|bool $avatar_dir The name of the subdirectory where the 
  130. * requested avatar should be found. If no value is passed,  
  131. * 'avatar_dir' is inferred from 'object': 'user' becomes 'avatars',  
  132. * 'group' becomes 'group-avatars', 'blog' becomes 'blog-avatars'. 
  133. * Remember that this string denotes a subdirectory of BP's main 
  134. * avatar directory (usually based on {@link wp_upload_dir()}); it's a 
  135. * string like 'group-avatars' rather than the full directory path. 
  136. * Generally, it'll only be necessary to override the default value if 
  137. * storing avatars in a non-default location. Defaults to false 
  138. * (auto-detected). 
  139. * @type int|bool $width Requested avatar width. The unit is px. This value 
  140. * is used to build the 'width' attribute for the <img> element. If 
  141. * no value is passed, BP uses the global avatar width for this 
  142. * avatar type. Default: false (auto-detected). 
  143. * @type int|bool $height Requested avatar height. The unit is px. This 
  144. * value is used to build the 'height' attribute for the <img> 
  145. * element. If no value is passed, BP uses the global avatar height 
  146. * for this avatar type. Default: false (auto-detected). 
  147. * @type string $class The CSS class for the <img> element. Note that BP 
  148. * uses the 'avatar' class fairly extensively in its default styling,  
  149. * so if you plan to pass a custom value, consider appending it to 
  150. * 'avatar' (eg 'avatar foo') rather than replacing it altogether. 
  151. * Default: 'avatar'. 
  152. * @type string|bool $css_id The CSS id for the <img> element. 
  153. * Default: false. 
  154. * @type string $title The title attribute for the <img> element. 
  155. * Default: false. 
  156. * @type string $alt The alt attribute for the <img> element. In BP, this 
  157. * value is generally passed by the wrapper functions, where the data 
  158. * necessary for concatenating the string is at hand; see 
  159. * {@link bp_get_activity_avatar()} for an example. Default: ''. 
  160. * @type string|bool $email An email to use in Gravatar queries. Unless 
  161. * otherwise configured, BP uses Gravatar as a fallback for avatars 
  162. * that are not provided locally. Gravatar's API requires using a hash 
  163. * of the user's email address; this argument provides it. If not 
  164. * provided, the function will infer it: for users, by getting the 
  165. * user's email from the database, for groups/blogs, by concatenating 
  166. * "{$item_id}-{$object}@{bp_get_root_domain()}". The user query adds 
  167. * overhead, so it's recommended that wrapper functions provide a 
  168. * value for 'email' when querying user IDs. Default: false. 
  169. * @type bool $no_grav Whether to disable the default Gravatar fallback. 
  170. * By default, BP will fall back on Gravatar when it cannot find a 
  171. * local avatar. In some cases, this may be undesirable, in which 
  172. * case 'no_grav' should be set to true. To disable Gravatar 
  173. * fallbacks globally, see the 'bp_core_fetch_avatar_no_grav' filter. 
  174. * Default: true for groups, otherwise false. 
  175. * @type bool $html Whether to return an <img> HTML element, vs a raw URL 
  176. * to an avatar. If false, <img>-specific arguments (like 'css_id') 
  177. * will be ignored. Default: true. 
  178. * @type string $extra_attr HTML attributes to insert in the IMG element. Not sanitized. Default: ''. 
  179. * @type string $scheme URL scheme to use. See set_url_scheme() for accepted values. 
  180. * Default null. 
  181. * @type string $rating What rating to display Gravatars for. Accepts 'G', 'PG', 'R', 'X'. 
  182. * Default is the value of the 'avatar_rating' option. 
  183. * @type bool $force_default Used when creating the Gravatar URL. Whether to force the default 
  184. * image regardless if the Gravatar exists. Default: false. 
  185. * } 
  186. * @return string Formatted HTML <img> element, or raw avatar URL based on $html arg. 
  187. */ 
  188. function bp_core_fetch_avatar( $args = '' ) { 
  189. $bp = buddypress(); 
  190.  
  191. // If avatars are disabled for the root site, obey that request and bail. 
  192. if ( ! $bp->avatar->show_avatars ) { 
  193. return; 
  194.  
  195. global $current_blog; 
  196.  
  197. // Set the default variables array and parse it against incoming $args array. 
  198. $params = wp_parse_args( $args, array( 
  199. 'item_id' => false,  
  200. 'object' => 'user',  
  201. 'type' => 'thumb',  
  202. 'avatar_dir' => false,  
  203. 'width' => false,  
  204. 'height' => false,  
  205. 'class' => 'avatar',  
  206. 'css_id' => false,  
  207. 'alt' => '',  
  208. 'email' => false,  
  209. 'no_grav' => null,  
  210. 'html' => true,  
  211. 'title' => '',  
  212. 'extra_attr' => '',  
  213. 'scheme' => null,  
  214. 'rating' => get_option( 'avatar_rating' ),  
  215. 'force_default' => false,  
  216. ) ); 
  217.  
  218. /** Set item_id ***********************************************************/ 
  219.  
  220. if ( empty( $params['item_id'] ) ) { 
  221.  
  222. switch ( $params['object'] ) { 
  223.  
  224. case 'blog' : 
  225. $params['item_id'] = $current_blog->id; 
  226. break; 
  227.  
  228. case 'group' : 
  229. if ( bp_is_active( 'groups' ) ) { 
  230. $params['item_id'] = $bp->groups->current_group->id; 
  231. } else { 
  232. $params['item_id'] = false; 
  233.  
  234. break; 
  235.  
  236. case 'user' : 
  237. default : 
  238. $params['item_id'] = bp_displayed_user_id(); 
  239. break; 
  240.  
  241. /** 
  242. * Filters the ID of the item being requested. 
  243. * 
  244. * @since 1.1.0 
  245. * 
  246. * @param string $value ID of avatar item being requested. 
  247. * @param string $value Avatar type being requested. 
  248. * @param array $params Array of parameters for the request. 
  249. */ 
  250. $params['item_id'] = apply_filters( 'bp_core_avatar_item_id', $params['item_id'], $params['object'], $params ); 
  251.  
  252. if ( empty( $params['item_id'] ) ) { 
  253. return false; 
  254.  
  255. /** Set avatar_dir ********************************************************/ 
  256.  
  257. if ( empty( $params['avatar_dir'] ) ) { 
  258.  
  259. switch ( $params['object'] ) { 
  260.  
  261. case 'blog' : 
  262. $params['avatar_dir'] = 'blog-avatars'; 
  263. break; 
  264.  
  265. case 'group' : 
  266. if ( bp_is_active( 'groups' ) ) { 
  267. $params['avatar_dir'] = 'group-avatars'; 
  268. } else { 
  269. $params['avatar_dir'] = false; 
  270.  
  271. break; 
  272.  
  273. case 'user' : 
  274. default : 
  275. $params['avatar_dir'] = 'avatars'; 
  276. break; 
  277.  
  278. /** 
  279. * Filters the avatar directory to use. 
  280. * 
  281. * @since 1.1.0 
  282. * 
  283. * @param string $value Name of the subdirectory where the requested avatar should be found. 
  284. * @param string $value Avatar type being requested. 
  285. * @param array $params Array of parameters for the request. 
  286. */ 
  287. $params['avatar_dir'] = apply_filters( 'bp_core_avatar_dir', $params['avatar_dir'], $params['object'], $params ); 
  288.  
  289. if ( empty( $params['avatar_dir'] ) ) { 
  290. return false; 
  291.  
  292. /** <img> alt *************************************************************/ 
  293.  
  294. if ( false !== strpos( $params['alt'], '%s' ) || false !== strpos( $params['alt'], '%1$s' ) ) { 
  295.  
  296. switch ( $params['object'] ) { 
  297.  
  298. case 'blog' : 
  299. $item_name = get_blog_option( $params['item_id'], 'blogname' ); 
  300. break; 
  301.  
  302. case 'group' : 
  303. $item_name = bp_get_group_name( groups_get_group( $params['item_id'] ) ); 
  304. break; 
  305.  
  306. case 'user' : 
  307. default : 
  308. $item_name = bp_core_get_user_displayname( $params['item_id'] ); 
  309. break; 
  310.  
  311. /** 
  312. * Filters the alt attribute value to be applied to avatar. 
  313. * 
  314. * @since 1.5.0 
  315. * 
  316. * @param string $value alt to be applied to avatar. 
  317. * @param string $value ID of avatar item being requested. 
  318. * @param string $value Avatar type being requested. 
  319. * @param array $params Array of parameters for the request. 
  320. */ 
  321. $item_name = apply_filters( 'bp_core_avatar_alt', $item_name, $params['item_id'], $params['object'], $params ); 
  322. $params['alt'] = sprintf( $params['alt'], $item_name ); 
  323.  
  324. /** Sanity Checks *********************************************************/ 
  325.  
  326. // Get a fallback for the 'alt' parameter, create html output. 
  327. if ( empty( $params['alt'] ) ) { 
  328. $params['alt'] = __( 'Profile Photo', 'buddypress' ); 
  329. $html_alt = ' alt="' . esc_attr( $params['alt'] ) . '"'; 
  330.  
  331. // Filter image title and create html string. 
  332. $html_title = ''; 
  333.  
  334. /** 
  335. * Filters the title attribute value to be applied to avatar. 
  336. * 
  337. * @since 1.5.0 
  338. * 
  339. * @param string $value Title to be applied to avatar. 
  340. * @param string $value ID of avatar item being requested. 
  341. * @param string $value Avatar type being requested. 
  342. * @param array $params Array of parameters for the request. 
  343. */ 
  344. $params['title'] = apply_filters( 'bp_core_avatar_title', $params['title'], $params['item_id'], $params['object'], $params ); 
  345.  
  346. if ( ! empty( $params['title'] ) ) { 
  347. $html_title = ' title="' . esc_attr( $params['title'] ) . '"'; 
  348.  
  349. // Extra attributes. 
  350. $extra_attr = ! empty( $args['extra_attr'] ) ? ' ' . $args['extra_attr'] : ''; 
  351.  
  352. // Set CSS ID and create html string. 
  353. $html_css_id = ''; 
  354.  
  355. /** 
  356. * Filters the ID attribute to be applied to avatar. 
  357. * 
  358. * @since 2.2.0 
  359. * 
  360. * @param string $value ID to be applied to avatar. 
  361. * @param string $value ID of avatar item being requested. 
  362. * @param string $value Avatar type being requested. 
  363. * @param array $params Array of parameters for the request. 
  364. */ 
  365. $params['css_id'] = apply_filters( 'bp_core_css_id', $params['css_id'], $params['item_id'], $params['object'], $params ); 
  366.  
  367. if ( ! empty( $params['css_id'] ) ) { 
  368. $html_css_id = ' id="' . esc_attr( $params['css_id'] ) . '"'; 
  369.  
  370. // Set image width. 
  371. if ( false !== $params['width'] ) { 
  372. // Width has been specified. No modification necessary. 
  373. } elseif ( 'thumb' == $params['type'] ) { 
  374. $params['width'] = bp_core_avatar_thumb_width(); 
  375. } else { 
  376. $params['width'] = bp_core_avatar_full_width(); 
  377. $html_width = ' width="' . $params['width'] . '"'; 
  378.  
  379. // Set image height. 
  380. if ( false !== $params['height'] ) { 
  381. // Height has been specified. No modification necessary. 
  382. } elseif ( 'thumb' == $params['type'] ) { 
  383. $params['height'] = bp_core_avatar_thumb_height(); 
  384. } else { 
  385. $params['height'] = bp_core_avatar_full_height(); 
  386. $html_height = ' height="' . $params['height'] . '"'; 
  387.  
  388. /** 
  389. * Filters the classes to be applied to the avatar. 
  390. * 
  391. * @since 1.6.0 
  392. * 
  393. * @param array|string $value Class(es) to be applied to the avatar. 
  394. * @param string $value ID of the avatar item being requested. 
  395. * @param string $value Avatar type being requested. 
  396. * @param array $params Array of parameters for the request. 
  397. */ 
  398. $params['class'] = apply_filters( 'bp_core_avatar_class', $params['class'], $params['item_id'], $params['object'], $params ); 
  399.  
  400. // Use an alias to leave the param unchanged. 
  401. $avatar_classes = $params['class']; 
  402. if ( ! is_array( $avatar_classes ) ) { 
  403. $avatar_classes = explode( ' ', $avatar_classes ); 
  404.  
  405. // Merge classes. 
  406. $avatar_classes = array_merge( $avatar_classes, array( 
  407. $params['object'] . '-' . $params['item_id'] . '-avatar',  
  408. 'avatar-' . $params['width'],  
  409. ) ); 
  410.  
  411. // Sanitize each class. 
  412. $avatar_classes = array_map( 'sanitize_html_class', $avatar_classes ); 
  413.  
  414. // Populate the class attribute. 
  415. $html_class = ' class="' . join( ' ', $avatar_classes ) . ' photo"'; 
  416.  
  417. // Set img URL and DIR based on prepopulated constants. 
  418. $avatar_loc = new stdClass(); 
  419. $avatar_loc->path = trailingslashit( bp_core_avatar_upload_path() ); 
  420. $avatar_loc->url = trailingslashit( bp_core_avatar_url() ); 
  421.  
  422. $avatar_loc->dir = trailingslashit( $params['avatar_dir'] ); 
  423.  
  424. /** 
  425. * Filters the avatar folder directory URL. 
  426. * 
  427. * @since 1.1.0 
  428. * 
  429. * @param string $value Path to the avatar folder URL. 
  430. * @param int $value ID of the avatar item being requested. 
  431. * @param string $value Avatar type being requested. 
  432. * @param string $value Subdirectory where the requested avatar should be found. 
  433. */ 
  434. $avatar_folder_url = apply_filters( 'bp_core_avatar_folder_url', ( $avatar_loc->url . $avatar_loc->dir . $params['item_id'] ), $params['item_id'], $params['object'], $params['avatar_dir'] ); 
  435.  
  436. /** 
  437. * Filters the avatar folder directory path. 
  438. * 
  439. * @since 1.1.0 
  440. * 
  441. * @param string $value Path to the avatar folder directory. 
  442. * @param int $value ID of the avatar item being requested. 
  443. * @param string $value Avatar type being requested. 
  444. * @param string $value Subdirectory where the requested avatar should be found. 
  445. */ 
  446. $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', ( $avatar_loc->path . $avatar_loc->dir . $params['item_id'] ), $params['item_id'], $params['object'], $params['avatar_dir'] ); 
  447.  
  448. /** 
  449. * Look for uploaded avatar first. Use it if it exists. 
  450. * Set the file names to search for, to select the full size 
  451. * or thumbnail image. 
  452. */ 
  453. $avatar_size = ( 'full' == $params['type'] ) ? '-bpfull' : '-bpthumb'; 
  454. $legacy_user_avatar_name = ( 'full' == $params['type'] ) ? '-avatar2' : '-avatar1'; 
  455. $legacy_group_avatar_name = ( 'full' == $params['type'] ) ? '-groupavatar-full' : '-groupavatar-thumb'; 
  456.  
  457. // Check for directory. 
  458. if ( file_exists( $avatar_folder_dir ) ) { 
  459.  
  460. // Open directory. 
  461. if ( $av_dir = opendir( $avatar_folder_dir ) ) { 
  462.  
  463. // Stash files in an array once to check for one that matches. 
  464. $avatar_files = array(); 
  465. while ( false !== ( $avatar_file = readdir( $av_dir ) ) ) { 
  466. // Only add files to the array (skip directories). 
  467. if ( 2 < strlen( $avatar_file ) ) { 
  468. $avatar_files[] = $avatar_file; 
  469.  
  470. // Check for array. 
  471. if ( 0 < count( $avatar_files ) ) { 
  472.  
  473. // Check for current avatar. 
  474. foreach( $avatar_files as $key => $value ) { 
  475. if ( strpos ( $value, $avatar_size )!== false ) { 
  476. $avatar_url = $avatar_folder_url . '/' . $avatar_files[$key]; 
  477.  
  478. // Legacy avatar check. 
  479. if ( !isset( $avatar_url ) ) { 
  480. foreach( $avatar_files as $key => $value ) { 
  481. if ( strpos ( $value, $legacy_user_avatar_name )!== false ) { 
  482. $avatar_url = $avatar_folder_url . '/' . $avatar_files[$key]; 
  483.  
  484. // Legacy group avatar check. 
  485. if ( !isset( $avatar_url ) ) { 
  486. foreach( $avatar_files as $key => $value ) { 
  487. if ( strpos ( $value, $legacy_group_avatar_name )!== false ) { 
  488. $avatar_url = $avatar_folder_url . '/' . $avatar_files[$key]; 
  489.  
  490. // Close the avatar directory. 
  491. closedir( $av_dir ); 
  492.  
  493. // If we found a locally uploaded avatar. 
  494. if ( isset( $avatar_url ) ) { 
  495. // Support custom scheme. 
  496. $avatar_url = set_url_scheme( $avatar_url, $params['scheme'] ); 
  497.  
  498. // Return it wrapped in an <img> element. 
  499. if ( true === $params['html'] ) { 
  500.  
  501. /** 
  502. * Filters an avatar URL wrapped in an <img> element. 
  503. * 
  504. * @since 1.1.0 
  505. * 
  506. * @param string $value Full <img> element for an avatar. 
  507. * @param array $params Array of parameters for the request. 
  508. * @param string $value ID of the item requested. 
  509. * @param string $value Subdirectory where the requested avatar should be found. 
  510. * @param string $html_css_id ID attribute for avatar. 
  511. * @param string $html_width Width attribute for avatar. 
  512. * @param string $html_height Height attribute for avatar. 
  513. * @param string $avatar_folder_url Avatar URL path. 
  514. * @param string $avatar_folder_dir Avatar DIR path. 
  515. */ 
  516. return apply_filters( 'bp_core_fetch_avatar', '<img src="' . $avatar_url . '"' . $html_class . $html_css_id . $html_width . $html_height . $html_alt . $html_title . $extra_attr . ' />', $params, $params['item_id'], $params['avatar_dir'], $html_css_id, $html_width, $html_height, $avatar_folder_url, $avatar_folder_dir ); 
  517.  
  518. // ...or only the URL 
  519. } else { 
  520.  
  521. /** 
  522. * Filters a locally uploaded avatar URL. 
  523. * 
  524. * @since 1.2.5 
  525. * 
  526. * @param string $avatar_url URL for a locally uploaded avatar. 
  527. * @param array $params Array of parameters for the request. 
  528. */ 
  529. return apply_filters( 'bp_core_fetch_avatar_url', $avatar_url, $params ); 
  530.  
  531. // By default, Gravatar is not pinged for groups. 
  532. if ( null === $params['no_grav'] ) { 
  533. $params['no_grav'] = 'group' === $params['object']; 
  534.  
  535. /** 
  536. * Filters whether or not to skip Gravatar check. 
  537. * 
  538. * @since 1.5.0 
  539. * 
  540. * @param bool $value Whether or not to skip Gravatar. 
  541. * @param array $params Array of parameters for the avatar request. 
  542. */ 
  543. if ( ! apply_filters( 'bp_core_fetch_avatar_no_grav', $params['no_grav'], $params ) ) { 
  544.  
  545. // Set gravatar type. 
  546. if ( empty( $bp->grav_default->{$params['object']} ) ) { 
  547. $default_grav = 'wavatar'; 
  548. } elseif ( 'mystery' == $bp->grav_default->{$params['object']} ) { 
  549.  
  550. /** 
  551. * Filters the Mystery person avatar src value. 
  552. * 
  553. * @since 1.2.0 
  554. * 
  555. * @param string $value Avatar value. 
  556. * @param string $value Width to display avatar at. 
  557. */ 
  558. $default_grav = apply_filters( 'bp_core_mysteryman_src', 'mm', $params['width'] ); 
  559. } else { 
  560. $default_grav = $bp->grav_default->{$params['object']}; 
  561.  
  562. // Set gravatar object. 
  563. if ( empty( $params['email'] ) ) { 
  564. if ( 'user' == $params['object'] ) { 
  565. $params['email'] = bp_core_get_user_email( $params['item_id'] ); 
  566. } elseif ( 'group' == $params['object'] || 'blog' == $params['object'] ) { 
  567. $params['email'] = $params['item_id'] . '-' . $params['object'] . '@' . bp_get_root_domain(); 
  568.  
  569. /** 
  570. * Filters the Gravatar email to use. 
  571. * 
  572. * @since 1.1.0 
  573. * 
  574. * @param string $value Email to use in Gravatar request. 
  575. * @param string $value ID of the item being requested. 
  576. * @param string $value Object type being requested. 
  577. */ 
  578. $params['email'] = apply_filters( 'bp_core_gravatar_email', $params['email'], $params['item_id'], $params['object'] ); 
  579.  
  580. /** 
  581. * Filters the Gravatar URL host. 
  582. * 
  583. * @since 1.0.2 
  584. * 
  585. * @param string $value Gravatar URL host. 
  586. */ 
  587. $gravatar = apply_filters( 'bp_gravatar_url', '//www.gravatar.com/avatar/' ); 
  588.  
  589. // Append email hash to Gravatar. 
  590. $gravatar .= md5( strtolower( $params['email'] ) ); 
  591.  
  592. // Main Gravatar URL args. 
  593. $url_args = array( 
  594. 's' => $params['width'] 
  595. ); 
  596.  
  597. // Custom Gravatar URL args. 
  598. if ( ! empty( $params['force_default'] ) ) { 
  599. $url_args['f'] = 'y'; 
  600. if ( ! empty( $params['rating'] ) ) { 
  601. $url_args['r'] = strtolower( $params['rating'] ); 
  602.  
  603. /** 
  604. * Filters the Gravatar "d" parameter. 
  605. * 
  606. * @since 2.6.0 
  607. * 
  608. * @param string $default_grav The avatar default. 
  609. * @param array $params The avatar's data. 
  610. */ 
  611. $default_grav = apply_filters( 'bp_core_avatar_default', $default_grav, $params ); 
  612.  
  613. // Only set default image if 'Gravatar Logo' is not requested. 
  614. if ( 'gravatar_default' !== $default_grav ) { 
  615. $url_args['d'] = $default_grav; 
  616.  
  617. // Set up the Gravatar URL. 
  618. $gravatar = esc_url( add_query_arg( 
  619. rawurlencode_deep( array_filter( $url_args ) ),  
  620. $gravatar 
  621. ) ); 
  622.  
  623. // No avatar was found, and we've been told not to use a gravatar. 
  624. } else { 
  625.  
  626. /** 
  627. * Filters the avatar default when Gravatar is not used. 
  628. * 
  629. * This is a variable filter dependent on the avatar type being requested. 
  630. * 
  631. * @since 1.5.0 
  632. * 
  633. * @param string $value Default avatar for non-gravatar requests. 
  634. * @param array $params Array of parameters for the avatar request. 
  635. */ 
  636. $gravatar = apply_filters( 'bp_core_default_avatar_' . $params['object'], bp_core_avatar_default( 'local', $params ), $params ); 
  637.  
  638. if ( true === $params['html'] ) { 
  639.  
  640. /** This filter is documented in bp-core/bp-core-avatars.php */ 
  641. return apply_filters( 'bp_core_fetch_avatar', '<img src="' . $gravatar . '"' . $html_css_id . $html_class . $html_width . $html_height . $html_alt . $html_title . $extra_attr . ' />', $params, $params['item_id'], $params['avatar_dir'], $html_css_id, $html_width, $html_height, $avatar_folder_url, $avatar_folder_dir ); 
  642. } else { 
  643.  
  644. /** This filter is documented in bp-core/bp-core-avatars.php */ 
  645. return apply_filters( 'bp_core_fetch_avatar_url', $gravatar, $params ); 
  646.  
  647. /** 
  648. * Delete an existing avatar. 
  649. * 
  650. * @since 1.1.0 
  651. * 
  652. * @param array|string $args { 
  653. * Array of function parameters. 
  654. * @type bool|int $item_id ID of the item whose avatar you're deleting. 
  655. * Defaults to the current item of type $object. 
  656. * @type string $object Object type of the item whose avatar you're 
  657. * deleting. 'user', 'group', 'blog', or custom. 
  658. * Default: 'user'. 
  659. * @type bool|string $avatar_dir Subdirectory where avatar is located. 
  660. * Default: false, which falls back on the default location 
  661. * corresponding to the $object. 
  662. * } 
  663. * @return bool True on success, false on failure. 
  664. */ 
  665. function bp_core_delete_existing_avatar( $args = '' ) { 
  666.  
  667. $defaults = array( 
  668. 'item_id' => false,  
  669. 'object' => 'user', // User OR group OR blog OR custom type (if you use filters). 
  670. 'avatar_dir' => false 
  671. ); 
  672.  
  673. $args = wp_parse_args( $args, $defaults ); 
  674. extract( $args, EXTR_SKIP ); 
  675.  
  676. /** 
  677. * Filters whether or not to handle deleting an existing avatar. 
  678. * 
  679. * If you want to override this function, make sure you return false. 
  680. * 
  681. * @since 2.5.1 
  682. * 
  683. * @param bool $value Whether or not to delete the avatar. 
  684. * @param array $args { 
  685. * Array of function parameters. 
  686. * 
  687. * @type bool|int $item_id ID of the item whose avatar you're deleting. 
  688. * Defaults to the current item of type $object. 
  689. * @type string $object Object type of the item whose avatar you're 
  690. * deleting. 'user', 'group', 'blog', or custom. 
  691. * Default: 'user'. 
  692. * @type bool|string $avatar_dir Subdirectory where avatar is located. 
  693. * Default: false, which falls back on the default location 
  694. * corresponding to the $object. 
  695. * } 
  696. */ 
  697. if ( ! apply_filters( 'bp_core_pre_delete_existing_avatar', true, $args ) ) { 
  698. return true; 
  699.  
  700. if ( empty( $item_id ) ) { 
  701. if ( 'user' == $object ) 
  702. $item_id = bp_displayed_user_id(); 
  703. elseif ( 'group' == $object ) 
  704. $item_id = buddypress()->groups->current_group->id; 
  705. elseif ( 'blog' == $object ) 
  706. $item_id = $current_blog->id; 
  707.  
  708. /** This filter is documented in bp-core/bp-core-avatars.php */ 
  709. $item_id = apply_filters( 'bp_core_avatar_item_id', $item_id, $object ); 
  710.  
  711. if ( !$item_id ) return false; 
  712.  
  713. if ( empty( $avatar_dir ) ) { 
  714. if ( 'user' == $object ) 
  715. $avatar_dir = 'avatars'; 
  716. elseif ( 'group' == $object ) 
  717. $avatar_dir = 'group-avatars'; 
  718. elseif ( 'blog' == $object ) 
  719. $avatar_dir = 'blog-avatars'; 
  720.  
  721. /** This filter is documented in bp-core/bp-core-avatars.php */ 
  722. $avatar_dir = apply_filters( 'bp_core_avatar_dir', $avatar_dir, $object ); 
  723.  
  724. if ( !$avatar_dir ) return false; 
  725.  
  726. /** This filter is documented in bp-core/bp-core-avatars.php */ 
  727. $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', bp_core_avatar_upload_path() . '/' . $avatar_dir . '/' . $item_id, $item_id, $object, $avatar_dir ); 
  728.  
  729. if ( !file_exists( $avatar_folder_dir ) ) 
  730. return false; 
  731.  
  732. if ( $av_dir = opendir( $avatar_folder_dir ) ) { 
  733. while ( false !== ( $avatar_file = readdir($av_dir) ) ) { 
  734. if ( ( preg_match( "/-bpfull/", $avatar_file ) || preg_match( "/-bpthumb/", $avatar_file ) ) && '.' != $avatar_file && '..' != $avatar_file ) 
  735. @unlink( $avatar_folder_dir . '/' . $avatar_file ); 
  736. closedir($av_dir); 
  737.  
  738. @rmdir( $avatar_folder_dir ); 
  739.  
  740. /** 
  741. * Fires after deleting an existing avatar. 
  742. * 
  743. * @since 1.1.0 
  744. * 
  745. * @param array $args Array of arguments used for avatar deletion. 
  746. */ 
  747. do_action( 'bp_core_delete_existing_avatar', $args ); 
  748.  
  749. return true; 
  750.  
  751. /** 
  752. * Ajax delete an avatar for a given object and item id. 
  753. * 
  754. * @since 2.3.0 
  755. * 
  756. * @return string|null A JSON object containing success data if the avatar was deleted,  
  757. * error message otherwise. 
  758. */ 
  759. function bp_avatar_ajax_delete() { 
  760. // Bail if not a POST action. 
  761. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 
  762. wp_send_json_error(); 
  763.  
  764. $avatar_data = $_POST; 
  765.  
  766. if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) ) { 
  767. wp_send_json_error(); 
  768.  
  769. $nonce = 'bp_delete_avatar_link'; 
  770. if ( 'group' === $avatar_data['object'] ) { 
  771. $nonce = 'bp_group_avatar_delete'; 
  772.  
  773. // Check the nonce. 
  774. check_admin_referer( $nonce, 'nonce' ); 
  775.  
  776. // Capability check. 
  777. if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) { 
  778. wp_send_json_error(); 
  779.  
  780. // Handle delete. 
  781. if ( bp_core_delete_existing_avatar( array( 'item_id' => $avatar_data['item_id'], 'object' => $avatar_data['object'] ) ) ) { 
  782. $return = array( 
  783. 'avatar' => html_entity_decode( bp_core_fetch_avatar( array( 
  784. 'object' => $avatar_data['object'],  
  785. 'item_id' => $avatar_data['item_id'],  
  786. 'html' => false,  
  787. 'type' => 'full',  
  788. ) ) ),  
  789. 'feedback_code' => 4,  
  790. 'item_id' => $avatar_data['item_id'],  
  791. ); 
  792.  
  793. wp_send_json_success( $return ); 
  794. } else { 
  795. wp_send_json_error( array( 
  796. 'feedback_code' => 3,  
  797. ) ); 
  798. add_action( 'wp_ajax_bp_avatar_delete', 'bp_avatar_ajax_delete' ); 
  799.  
  800. /** 
  801. * Handle avatar uploading. 
  802. * 
  803. * The functions starts off by checking that the file has been uploaded 
  804. * properly using bp_core_check_avatar_upload(). It then checks that the file 
  805. * size is within limits, and that it has an accepted file extension (jpg, gif,  
  806. * png). If everything checks out, crop the image and move it to its real 
  807. * location. 
  808. * 
  809. * @since 1.1.0 
  810. * 
  811. * @see bp_core_check_avatar_upload() 
  812. * @see bp_core_check_avatar_type() 
  813. * 
  814. * @param array $file The appropriate entry the from $_FILES superglobal. 
  815. * @param string $upload_dir_filter A filter to be applied to 'upload_dir'. 
  816. * @return bool True on success, false on failure. 
  817. */ 
  818. function bp_core_avatar_handle_upload( $file, $upload_dir_filter ) { 
  819.  
  820. /** 
  821. * Filters whether or not to handle uploading. 
  822. * 
  823. * If you want to override this function, make sure you return false. 
  824. * 
  825. * @since 1.2.4 
  826. * 
  827. * @param bool $value Whether or not to crop. 
  828. * @param array $file Appropriate entry from $_FILES superglobal. 
  829. * @parma string $upload_dir_filter A filter to be applied to 'upload_dir'. 
  830. */ 
  831. if ( ! apply_filters( 'bp_core_pre_avatar_handle_upload', true, $file, $upload_dir_filter ) ) { 
  832. return true; 
  833.  
  834. // Setup some variables. 
  835. $bp = buddypress(); 
  836. $upload_path = bp_core_avatar_upload_path(); 
  837.  
  838. // Upload the file. 
  839. $avatar_attachment = new BP_Attachment_Avatar(); 
  840. $bp->avatar_admin->original = $avatar_attachment->upload( $file, $upload_dir_filter ); 
  841.  
  842. // In case of an error, stop the process and display a feedback to the user. 
  843. if ( ! empty( $bp->avatar_admin->original['error'] ) ) { 
  844. bp_core_add_message( sprintf( __( 'Upload Failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->original['error'] ), 'error' ); 
  845. return false; 
  846.  
  847. // The Avatar UI available width. 
  848. $ui_available_width = 0; 
  849.  
  850. // Try to set the ui_available_width using the avatar_admin global. 
  851. if ( isset( $bp->avatar_admin->ui_available_width ) ) { 
  852. $ui_available_width = $bp->avatar_admin->ui_available_width; 
  853.  
  854. // Maybe resize. 
  855. $bp->avatar_admin->resized = $avatar_attachment->shrink( $bp->avatar_admin->original['file'], $ui_available_width ); 
  856. $bp->avatar_admin->image = new stdClass(); 
  857.  
  858. // We only want to handle one image after resize. 
  859. if ( empty( $bp->avatar_admin->resized ) ) { 
  860. $bp->avatar_admin->image->file = $bp->avatar_admin->original['file']; 
  861. $bp->avatar_admin->image->dir = str_replace( $upload_path, '', $bp->avatar_admin->original['file'] ); 
  862. } else { 
  863. $bp->avatar_admin->image->file = $bp->avatar_admin->resized['path']; 
  864. $bp->avatar_admin->image->dir = str_replace( $upload_path, '', $bp->avatar_admin->resized['path'] ); 
  865. @unlink( $bp->avatar_admin->original['file'] ); 
  866.  
  867. // Check for WP_Error on what should be an image. 
  868. if ( is_wp_error( $bp->avatar_admin->image->dir ) ) { 
  869. bp_core_add_message( sprintf( __( 'Upload failed! Error was: %s', 'buddypress' ), $bp->avatar_admin->image->dir->get_error_message() ), 'error' ); 
  870. return false; 
  871.  
  872. // If the uploaded image is smaller than the "full" dimensions, throw a warning. 
  873. if ( $avatar_attachment->is_too_small( $bp->avatar_admin->image->file ) ) { 
  874. bp_core_add_message( sprintf( __( 'You have selected an image that is smaller than recommended. For best results, upload a picture larger than %d x %d pixels.', 'buddypress' ), bp_core_avatar_full_width(), bp_core_avatar_full_height() ), 'error' ); 
  875.  
  876. // Set the url value for the image. 
  877. $bp->avatar_admin->image->url = bp_core_avatar_url() . $bp->avatar_admin->image->dir; 
  878.  
  879. return true; 
  880.  
  881. /** 
  882. * Ajax upload an avatar. 
  883. * 
  884. * @since 2.3.0 
  885. * 
  886. * @return string|null A JSON object containing success data if the upload succeeded 
  887. * error message otherwise. 
  888. */ 
  889. function bp_avatar_ajax_upload() { 
  890. // Bail if not a POST action. 
  891. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 
  892. wp_die(); 
  893.  
  894. /** 
  895. * Sending the json response will be different if 
  896. * the current Plupload runtime is html4. 
  897. */ 
  898. $is_html4 = false; 
  899. if ( ! empty( $_POST['html4' ] ) ) { 
  900. $is_html4 = true; 
  901.  
  902. // Check the nonce. 
  903. check_admin_referer( 'bp-uploader' ); 
  904.  
  905. // Init the BuddyPress parameters. 
  906. $bp_params = array(); 
  907.  
  908. // We need it to carry on. 
  909. if ( ! empty( $_POST['bp_params' ] ) ) { 
  910. $bp_params = $_POST['bp_params' ]; 
  911. } else { 
  912. bp_attachments_json_response( false, $is_html4 ); 
  913.  
  914. // We need the object to set the uploads dir filter. 
  915. if ( empty( $bp_params['object'] ) ) { 
  916. bp_attachments_json_response( false, $is_html4 ); 
  917.  
  918. // Capability check. 
  919. if ( ! bp_attachments_current_user_can( 'edit_avatar', $bp_params ) ) { 
  920. bp_attachments_json_response( false, $is_html4 ); 
  921.  
  922. $bp = buddypress(); 
  923. $bp_params['upload_dir_filter'] = ''; 
  924. $needs_reset = array(); 
  925.  
  926. if ( 'user' === $bp_params['object'] && bp_is_active( 'xprofile' ) ) { 
  927. $bp_params['upload_dir_filter'] = 'xprofile_avatar_upload_dir'; 
  928.  
  929. if ( ! bp_displayed_user_id() && ! empty( $bp_params['item_id'] ) ) { 
  930. $needs_reset = array( 'key' => 'displayed_user', 'value' => $bp->displayed_user ); 
  931. $bp->displayed_user->id = $bp_params['item_id']; 
  932. } elseif ( 'group' === $bp_params['object'] && bp_is_active( 'groups' ) ) { 
  933. $bp_params['upload_dir_filter'] = 'groups_avatar_upload_dir'; 
  934.  
  935. if ( ! bp_get_current_group_id() && ! empty( $bp_params['item_id'] ) ) { 
  936. $needs_reset = array( 'component' => 'groups', 'key' => 'current_group', 'value' => $bp->groups->current_group ); 
  937. $bp->groups->current_group = groups_get_group( $bp_params['item_id'] ); 
  938. } else { 
  939. /** 
  940. * Filter here to deal with other components. 
  941. * 
  942. * @since 2.3.0 
  943. * 
  944. * @var array $bp_params the BuddyPress Ajax parameters. 
  945. */ 
  946. $bp_params = apply_filters( 'bp_core_avatar_ajax_upload_params', $bp_params ); 
  947.  
  948. if ( ! isset( $bp->avatar_admin ) ) { 
  949. $bp->avatar_admin = new stdClass(); 
  950.  
  951. /** 
  952. * The BuddyPress upload parameters is including the Avatar UI Available width,  
  953. * add it to the avatar_admin global for a later use. 
  954. */ 
  955. if ( isset( $bp_params['ui_available_width'] ) ) { 
  956. $bp->avatar_admin->ui_available_width = (int) $bp_params['ui_available_width']; 
  957.  
  958. // Upload the avatar. 
  959. $avatar = bp_core_avatar_handle_upload( $_FILES, $bp_params['upload_dir_filter'] ); 
  960.  
  961. // Reset objects. 
  962. if ( ! empty( $needs_reset ) ) { 
  963. if ( ! empty( $needs_reset['component'] ) ) { 
  964. $bp->{$needs_reset['component']}->{$needs_reset['key']} = $needs_reset['value']; 
  965. } else { 
  966. $bp->{$needs_reset['key']} = $needs_reset['value']; 
  967.  
  968. // Init the feedback message. 
  969. $feedback_message = false; 
  970.  
  971. if ( ! empty( $bp->template_message ) ) { 
  972. $feedback_message = $bp->template_message; 
  973.  
  974. // Remove template message. 
  975. $bp->template_message = false; 
  976. $bp->template_message_type = false; 
  977.  
  978. @setcookie( 'bp-message', false, time() - 1000, COOKIEPATH, COOKIE_DOMAIN, is_ssl() ); 
  979. @setcookie( 'bp-message-type', false, time() - 1000, COOKIEPATH, COOKIE_DOMAIN, is_ssl() ); 
  980.  
  981. if ( empty( $avatar ) ) { 
  982. // Default upload error. 
  983. $message = __( 'Upload failed.', 'buddypress' ); 
  984.  
  985. // Use the template message if set. 
  986. if ( ! empty( $feedback_message ) ) { 
  987. $message = $feedback_message; 
  988.  
  989. // Upload error reply. 
  990. bp_attachments_json_response( false, $is_html4, array( 
  991. 'type' => 'upload_error',  
  992. 'message' => $message,  
  993. ) ); 
  994.  
  995. if ( empty( $bp->avatar_admin->image->file ) ) { 
  996. bp_attachments_json_response( false, $is_html4 ); 
  997.  
  998. $uploaded_image = @getimagesize( $bp->avatar_admin->image->file ); 
  999.  
  1000. // Set the name of the file. 
  1001. $name = $_FILES['file']['name']; 
  1002. $name_parts = pathinfo( $name ); 
  1003. $name = trim( substr( $name, 0, - ( 1 + strlen( $name_parts['extension'] ) ) ) ); 
  1004.  
  1005. // Finally return the avatar to the editor. 
  1006. bp_attachments_json_response( true, $is_html4, array( 
  1007. 'name' => $name,  
  1008. 'url' => $bp->avatar_admin->image->url,  
  1009. 'width' => $uploaded_image[0],  
  1010. 'height' => $uploaded_image[1],  
  1011. 'feedback' => $feedback_message,  
  1012. ) ); 
  1013. add_action( 'wp_ajax_bp_avatar_upload', 'bp_avatar_ajax_upload' ); 
  1014.  
  1015. /** 
  1016. * Handle avatar webcam capture. 
  1017. * 
  1018. * @since 2.3.0 
  1019. * 
  1020. * @param string $data Base64 encoded image. 
  1021. * @param int $item_id Item to associate. 
  1022. * @return bool True on success, false on failure. 
  1023. */ 
  1024. function bp_avatar_handle_capture( $data = '', $item_id = 0 ) { 
  1025. if ( empty( $data ) || empty( $item_id ) ) { 
  1026. return false; 
  1027.  
  1028. /** 
  1029. * Filters whether or not to handle avatar webcam capture. 
  1030. * 
  1031. * If you want to override this function, make sure you return false. 
  1032. * 
  1033. * @since 2.5.1 
  1034. * 
  1035. * @param bool $value Whether or not to crop. 
  1036. * @param string $data Base64 encoded image. 
  1037. * @param int $item_id Item to associate. 
  1038. */ 
  1039. if ( ! apply_filters( 'bp_avatar_pre_handle_capture', true, $data, $item_id ) ) { 
  1040. return true; 
  1041.  
  1042. $avatar_dir = bp_core_avatar_upload_path() . '/avatars'; 
  1043.  
  1044. // It's not a regular upload, we may need to create this folder. 
  1045. if ( ! file_exists( $avatar_dir ) ) { 
  1046. if ( ! wp_mkdir_p( $avatar_dir ) ) { 
  1047. return false; 
  1048.  
  1049. /** 
  1050. * Filters the Avatar folder directory. 
  1051. * 
  1052. * @since 2.3.0 
  1053. * 
  1054. * @param string $avatar_dir Directory for storing avatars. 
  1055. * @param int $item_id ID of the item being acted on. 
  1056. * @param string $value Avatar type. 
  1057. * @param string $value Avatars word. 
  1058. */ 
  1059. $avatar_folder_dir = apply_filters( 'bp_core_avatar_folder_dir', $avatar_dir . '/' . $item_id, $item_id, 'user', 'avatars' ); 
  1060.  
  1061. // It's not a regular upload, we may need to create this folder. 
  1062. if( ! is_dir( $avatar_folder_dir ) ) { 
  1063. if ( ! wp_mkdir_p( $avatar_folder_dir ) ) { 
  1064. return false; 
  1065.  
  1066. $original_file = $avatar_folder_dir . '/webcam-capture-' . $item_id . '.png'; 
  1067.  
  1068. if ( file_put_contents( $original_file, $data ) ) { 
  1069. $avatar_to_crop = str_replace( bp_core_avatar_upload_path(), '', $original_file ); 
  1070.  
  1071. // Crop to default values. 
  1072. $crop_args = array( 'item_id' => $item_id, 'original_file' => $avatar_to_crop, 'crop_x' => 0, 'crop_y' => 0 ); 
  1073.  
  1074. return bp_core_avatar_handle_crop( $crop_args ); 
  1075. } else { 
  1076. return false; 
  1077.  
  1078. /** 
  1079. * Crop an uploaded avatar. 
  1080. * 
  1081. * @since 1.1.0 
  1082. * 
  1083. * @param array|string $args { 
  1084. * Array of function parameters. 
  1085. * 
  1086. * @type string $object Object type of the item whose avatar you're 
  1087. * handling. 'user', 'group', 'blog', or custom. 
  1088. * Default: 'user'. 
  1089. * @type string $avatar_dir Subdirectory where avatar should be stored. 
  1090. * Default: 'avatars'. 
  1091. * @type bool|int $item_id ID of the item that the avatar belongs to. 
  1092. * @type bool|string $original_file Absolute path to the original avatar file. 
  1093. * @type int $crop_w Crop width. Default: the global 'full' avatar width,  
  1094. * as retrieved by bp_core_avatar_full_width(). 
  1095. * @type int $crop_h Crop height. Default: the global 'full' avatar height,  
  1096. * as retrieved by bp_core_avatar_full_height(). 
  1097. * @type int $crop_x The horizontal starting point of the crop. Default: 0. 
  1098. * @type int $crop_y The vertical starting point of the crop. Default: 0. 
  1099. * } 
  1100. * @return bool True on success, false on failure. 
  1101. */ 
  1102. function bp_core_avatar_handle_crop( $args = '' ) { 
  1103.  
  1104. $r = wp_parse_args( $args, array( 
  1105. 'object' => 'user',  
  1106. 'avatar_dir' => 'avatars',  
  1107. 'item_id' => false,  
  1108. 'original_file' => false,  
  1109. 'crop_w' => bp_core_avatar_full_width(),  
  1110. 'crop_h' => bp_core_avatar_full_height(),  
  1111. 'crop_x' => 0,  
  1112. 'crop_y' => 0 
  1113. ) ); 
  1114.  
  1115. /** 
  1116. * Filters whether or not to handle cropping. 
  1117. * 
  1118. * If you want to override this function, make sure you return false. 
  1119. * 
  1120. * @since 1.2.4 
  1121. * 
  1122. * @param bool $value Whether or not to crop. 
  1123. * @param array $r Array of parsed arguments for function. 
  1124. */ 
  1125. if ( ! apply_filters( 'bp_core_pre_avatar_handle_crop', true, $r ) ) { 
  1126. return true; 
  1127.  
  1128. // Crop the file. 
  1129. $avatar_attachment = new BP_Attachment_Avatar(); 
  1130. $cropped = $avatar_attachment->crop( $r ); 
  1131.  
  1132. // Check for errors. 
  1133. if ( empty( $cropped['full'] ) || empty( $cropped['thumb'] ) || is_wp_error( $cropped['full'] ) || is_wp_error( $cropped['thumb'] ) ) { 
  1134. return false; 
  1135.  
  1136. return true; 
  1137.  
  1138. /** 
  1139. * Ajax set an avatar for a given object and item id. 
  1140. * 
  1141. * @since 2.3.0 
  1142. * 
  1143. * @return string|null A JSON object containing success data if the crop/capture succeeded 
  1144. * error message otherwise. 
  1145. */ 
  1146. function bp_avatar_ajax_set() { 
  1147. // Bail if not a POST action. 
  1148. if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { 
  1149. wp_send_json_error(); 
  1150.  
  1151. // Check the nonce. 
  1152. check_admin_referer( 'bp_avatar_cropstore', 'nonce' ); 
  1153.  
  1154. $avatar_data = wp_parse_args( $_POST, array( 
  1155. 'crop_w' => bp_core_avatar_full_width(),  
  1156. 'crop_h' => bp_core_avatar_full_height(),  
  1157. 'crop_x' => 0,  
  1158. 'crop_y' => 0 
  1159. ) ); 
  1160.  
  1161. if ( empty( $avatar_data['object'] ) || empty( $avatar_data['item_id'] ) || empty( $avatar_data['original_file'] ) ) { 
  1162. wp_send_json_error(); 
  1163.  
  1164. // Capability check. 
  1165. if ( ! bp_attachments_current_user_can( 'edit_avatar', $avatar_data ) ) { 
  1166. wp_send_json_error(); 
  1167.  
  1168. if ( ! empty( $avatar_data['type'] ) && 'camera' === $avatar_data['type'] && 'user' === $avatar_data['object'] ) { 
  1169. $webcam_avatar = false; 
  1170.  
  1171. if ( ! empty( $avatar_data['original_file'] ) ) { 
  1172. $webcam_avatar = str_replace( array( 'data:image/png;base64, ', ' ' ), array( '', '+' ), $avatar_data['original_file'] ); 
  1173. $webcam_avatar = base64_decode( $webcam_avatar ); 
  1174.  
  1175. if ( ! bp_avatar_handle_capture( $webcam_avatar, $avatar_data['item_id'] ) ) { 
  1176. wp_send_json_error( array( 
  1177. 'feedback_code' => 1 
  1178. ) ); 
  1179.  
  1180. } else { 
  1181. $return = array( 
  1182. 'avatar' => html_entity_decode( bp_core_fetch_avatar( array( 
  1183. 'object' => $avatar_data['object'],  
  1184. 'item_id' => $avatar_data['item_id'],  
  1185. 'html' => false,  
  1186. 'type' => 'full',  
  1187. ) ) ),  
  1188. 'feedback_code' => 2,  
  1189. 'item_id' => $avatar_data['item_id'],  
  1190. ); 
  1191.  
  1192. /** 
  1193. * Fires if the new avatar was successfully captured. 
  1194. * 
  1195. * @since 1.1.0 Used to inform the avatar was successfully cropped 
  1196. * @since 2.3.4 Add two new parameters to inform about the user id and 
  1197. * about the way the avatar was set (eg: 'crop' or 'camera') 
  1198. * Move the action at the right place, once the avatar is set 
  1199. * @since 2.8.0 Added the `$avatar_data` parameter. 
  1200. * 
  1201. * @param string $item_id Inform about the user id the avatar was set for. 
  1202. * @param string $type Inform about the way the avatar was set ('camera'). 
  1203. * @param array $avatar_data Array of parameters passed to the avatar handler. 
  1204. */ 
  1205. do_action( 'xprofile_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $avatar_data ); 
  1206.  
  1207. wp_send_json_success( $return ); 
  1208.  
  1209. return; 
  1210.  
  1211. $original_file = str_replace( bp_core_avatar_url(), '', $avatar_data['original_file'] ); 
  1212.  
  1213. // Set avatars dir & feedback part. 
  1214. if ( 'user' === $avatar_data['object'] ) { 
  1215. $avatar_dir = 'avatars'; 
  1216.  
  1217. // Defaults to object-avatars dir. 
  1218. } else { 
  1219. $avatar_dir = sanitize_key( $avatar_data['object'] ) . '-avatars'; 
  1220.  
  1221. // Crop args. 
  1222. $r = array( 
  1223. 'item_id' => $avatar_data['item_id'],  
  1224. 'object' => $avatar_data['object'],  
  1225. 'avatar_dir' => $avatar_dir,  
  1226. 'original_file' => $original_file,  
  1227. 'crop_w' => $avatar_data['crop_w'],  
  1228. 'crop_h' => $avatar_data['crop_h'],  
  1229. 'crop_x' => $avatar_data['crop_x'],  
  1230. 'crop_y' => $avatar_data['crop_y'] 
  1231. ); 
  1232.  
  1233. // Handle crop. 
  1234. if ( bp_core_avatar_handle_crop( $r ) ) { 
  1235. $return = array( 
  1236. 'avatar' => html_entity_decode( bp_core_fetch_avatar( array( 
  1237. 'object' => $avatar_data['object'],  
  1238. 'item_id' => $avatar_data['item_id'],  
  1239. 'html' => false,  
  1240. 'type' => 'full',  
  1241. ) ) ),  
  1242. 'feedback_code' => 2,  
  1243. 'item_id' => $avatar_data['item_id'],  
  1244. ); 
  1245.  
  1246. if ( 'user' === $avatar_data['object'] ) { 
  1247. /** This action is documented in bp-core/bp-core-avatars.php */ 
  1248. do_action( 'xprofile_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r ); 
  1249. } elseif ( 'group' === $avatar_data['object'] ) { 
  1250. /** This action is documented in bp-groups/bp-groups-screens.php */ 
  1251. do_action( 'groups_avatar_uploaded', (int) $avatar_data['item_id'], $avatar_data['type'], $r ); 
  1252.  
  1253. wp_send_json_success( $return ); 
  1254. } else { 
  1255. wp_send_json_error( array( 
  1256. 'feedback_code' => 1,  
  1257. ) ); 
  1258. add_action( 'wp_ajax_bp_avatar_set', 'bp_avatar_ajax_set' ); 
  1259.  
  1260. /** 
  1261. * Replace default WordPress avatars with BP avatars, if available. 
  1262. * 
  1263. * See 'get_avatar' filter description in wp-includes/pluggable.php. 
  1264. * 
  1265. * @since 1.1.0 
  1266. * @since 2.4.0 Added $args parameter to coincide with WordPress 4.2.0. 
  1267. * 
  1268. * @param string $avatar The avatar path passed to 'get_avatar'. 
  1269. * @param int|string|object $user A user ID, email address, or comment object. 
  1270. * @param int $size Size of the avatar image ('thumb' or 'full'). 
  1271. * @param string $default URL to a default image to use if no avatar is available. 
  1272. * @param string $alt Alternate text to use in image tag. Default: ''. 
  1273. * @param array $args Arguments passed to get_avatar_data(), after processing. 
  1274. * @return string BP avatar path, if found; else the original avatar path. 
  1275. */ 
  1276. function bp_core_fetch_avatar_filter( $avatar, $user, $size, $default, $alt = '', $args = array() ) { 
  1277. global $pagenow; 
  1278.  
  1279. // Don't filter if inside WordPress options page and force_default is true. 
  1280. if ( 'options-discussion.php' === $pagenow && true === $args['force_default'] ) { 
  1281. return $avatar; 
  1282.  
  1283. // If passed an object, assume $user->user_id. 
  1284. if ( is_object( $user ) ) { 
  1285. if ( isset( $user->user_id ) ) { 
  1286. $id = $user->user_id; 
  1287. } else { 
  1288. $id = $user->ID; 
  1289.  
  1290. // If passed a number, assume it was a $user_id. 
  1291. } elseif ( is_numeric( $user ) ) { 
  1292. $id = $user; 
  1293.  
  1294. // If passed a string and that string returns a user, get the $id. 
  1295. } elseif ( is_string( $user ) && ( $user_by_email = get_user_by( 'email', $user ) ) ) { 
  1296. $id = $user_by_email->ID; 
  1297.  
  1298. // If somehow $id hasn't been assigned, return the result of get_avatar. 
  1299. if ( empty( $id ) ) { 
  1300. return !empty( $avatar ) ? $avatar : $default; 
  1301.  
  1302. // Image alt tag. 
  1303. if ( empty( $alt ) ) { 
  1304. $alt = sprintf( __( 'Profile photo of %s', 'buddypress' ), bp_core_get_user_displayname( $id ) ); 
  1305.  
  1306. // Use the 'thumb' type, unless the requested width is bigger than 
  1307. // BP's thumb width. 
  1308. $type = 'thumb'; 
  1309. if ( (int) $size > bp_core_avatar_thumb_width() ) { 
  1310. $type = 'full'; 
  1311.  
  1312. $avatar_args = array( 
  1313. 'item_id' => $id,  
  1314. 'type' => $type,  
  1315. 'width' => $size,  
  1316. 'height' => $size,  
  1317. 'alt' => $alt,  
  1318. ); 
  1319.  
  1320. // Support new arguments as of WordPress 4.2.0. 
  1321. if ( ! empty( $args['width'] ) ) { 
  1322. $avatar_args['width'] = $args['width']; 
  1323. if ( ! empty( $args['height'] ) ) { 
  1324. $avatar_args['height'] = $args['height']; 
  1325. if ( ! empty( $args['class'] ) ) { 
  1326. $avatar_args['class'] = $args['class']; 
  1327. if ( ! empty( $args['class'] ) ) { 
  1328. $avatar_args['class'] = $args['class']; 
  1329. if ( ! empty( $args['extra_attr'] ) ) { 
  1330. $avatar_args['extra_attr'] = $args['extra_attr']; 
  1331. if ( ! empty( $args['scheme'] ) ) { 
  1332. $avatar_args['scheme'] = $args['scheme']; 
  1333. if ( ! empty( $args['force_default'] ) ) { 
  1334. $avatar_args['force_default'] = $args['force_default']; 
  1335. if ( ! empty( $args['rating'] ) ) { 
  1336. $avatar_args['rating'] = $args['rating']; 
  1337.  
  1338. // Let BuddyPress handle the fetching of the avatar. 
  1339. $bp_avatar = bp_core_fetch_avatar( $avatar_args ); 
  1340.  
  1341. // If BuddyPress found an avatar, use it. If not, use the result of get_avatar. 
  1342. return ( !$bp_avatar ) ? $avatar : $bp_avatar; 
  1343. add_filter( 'get_avatar', 'bp_core_fetch_avatar_filter', 10, 6 ); 
  1344.  
  1345. /** 
  1346. * Is the current avatar upload error-free? 
  1347. * 
  1348. * @since 1.0.0 
  1349. * 
  1350. * @param array $file The $_FILES array. 
  1351. * @return bool True if no errors are found. False if there are errors. 
  1352. */ 
  1353. function bp_core_check_avatar_upload( $file ) { 
  1354. if ( isset( $file['error'] ) && $file['error'] ) 
  1355. return false; 
  1356.  
  1357. return true; 
  1358.  
  1359. /** 
  1360. * Is the file size of the current avatar upload permitted? 
  1361. * 
  1362. * @since 1.0.0 
  1363. * 
  1364. * @param array $file The $_FILES array. 
  1365. * @return bool True if the avatar is under the size limit, otherwise false. 
  1366. */ 
  1367. function bp_core_check_avatar_size( $file ) { 
  1368. if ( $file['file']['size'] > bp_core_avatar_original_max_filesize() ) 
  1369. return false; 
  1370.  
  1371. return true; 
  1372.  
  1373. /** 
  1374. * Get allowed avatar types. 
  1375. * 
  1376. * @since 2.3.0 
  1377. * 
  1378. * @return array 
  1379. */ 
  1380. function bp_core_get_allowed_avatar_types() { 
  1381. $allowed_types = bp_attachments_get_allowed_types( 'avatar' ); 
  1382.  
  1383. /** 
  1384. * Filters the list of allowed image types. 
  1385. * 
  1386. * @since 2.3.0 
  1387. * 
  1388. * @param array $allowed_types List of image types. 
  1389. */ 
  1390. $avatar_types = (array) apply_filters( 'bp_core_get_allowed_avatar_types', $allowed_types ); 
  1391.  
  1392. if ( empty( $avatar_types ) ) { 
  1393. $avatar_types = $allowed_types; 
  1394. } else { 
  1395. $avatar_types = array_intersect( $allowed_types, $avatar_types ); 
  1396.  
  1397. return array_values( $avatar_types ); 
  1398.  
  1399. /** 
  1400. * Get allowed avatar mime types. 
  1401. * 
  1402. * @since 2.3.0 
  1403. * 
  1404. * @return array 
  1405. */ 
  1406. function bp_core_get_allowed_avatar_mimes() { 
  1407. $allowed_types = bp_core_get_allowed_avatar_types(); 
  1408.  
  1409. return bp_attachments_get_allowed_mimes( 'avatar', $allowed_types ); 
  1410.  
  1411. /** 
  1412. * Does the current avatar upload have an allowed file type? 
  1413. * 
  1414. * Permitted file types are JPG, GIF and PNG. 
  1415. * 
  1416. * @since 1.0.0 
  1417. * 
  1418. * @param array $file The $_FILES array. 
  1419. * @return bool True if the file extension is permitted, otherwise false. 
  1420. */ 
  1421. function bp_core_check_avatar_type( $file ) { 
  1422. return bp_attachments_check_filetype( $file['file']['tmp_name'], $file['file']['name'], bp_core_get_allowed_avatar_mimes() ); 
  1423.  
  1424. /** 
  1425. * Fetch data from the BP root blog's upload directory. 
  1426. * 
  1427. * @since 1.8.0 
  1428. * 
  1429. * @param string $type The variable we want to return from the $bp->avatars object. 
  1430. * Only 'upload_path' and 'url' are supported. Default: 'upload_path'. 
  1431. * @return string The avatar upload directory path. 
  1432. */ 
  1433. function bp_core_get_upload_dir( $type = 'upload_path' ) { 
  1434. $bp = buddypress(); 
  1435.  
  1436. switch ( $type ) { 
  1437. case 'upload_path' : 
  1438. $constant = 'BP_AVATAR_UPLOAD_PATH'; 
  1439. $key = 'basedir'; 
  1440.  
  1441. break; 
  1442.  
  1443. case 'url' : 
  1444. $constant = 'BP_AVATAR_URL'; 
  1445. $key = 'baseurl'; 
  1446.  
  1447. break; 
  1448.  
  1449. default : 
  1450. return false; 
  1451.  
  1452. break; 
  1453.  
  1454. // See if the value has already been calculated and stashed in the $bp global. 
  1455. if ( isset( $bp->avatar->$type ) ) { 
  1456. $retval = $bp->avatar->$type; 
  1457. } else { 
  1458. // If this value has been set in a constant, just use that. 
  1459. if ( defined( $constant ) ) { 
  1460. $retval = constant( $constant ); 
  1461. } else { 
  1462.  
  1463. // Use cached upload dir data if available. 
  1464. if ( ! empty( $bp->avatar->upload_dir ) ) { 
  1465. $upload_dir = $bp->avatar->upload_dir; 
  1466.  
  1467. // No cache, so query for it. 
  1468. } else { 
  1469.  
  1470. // Get upload directory information from current site. 
  1471. $upload_dir = bp_upload_dir(); 
  1472.  
  1473. // Stash upload directory data for later use. 
  1474. $bp->avatar->upload_dir = $upload_dir; 
  1475.  
  1476. // Directory does not exist and cannot be created. 
  1477. if ( ! empty( $upload_dir['error'] ) ) { 
  1478. $retval = ''; 
  1479.  
  1480. } else { 
  1481. $retval = $upload_dir[$key]; 
  1482.  
  1483. // If $key is 'baseurl', check to see if we're on SSL 
  1484. // Workaround for WP13941, WP15928, WP19037. 
  1485. if ( $key == 'baseurl' && is_ssl() ) { 
  1486. $retval = str_replace( 'http://', 'https://', $retval ); 
  1487.  
  1488.  
  1489. // Stash in $bp for later use. 
  1490. $bp->avatar->$type = $retval; 
  1491.  
  1492. return $retval; 
  1493.  
  1494. /** 
  1495. * Get the absolute upload path for the WP installation. 
  1496. * 
  1497. * @since 1.2.0 
  1498. * 
  1499. * @return string Absolute path to WP upload directory. 
  1500. */ 
  1501. function bp_core_avatar_upload_path() { 
  1502.  
  1503. /** 
  1504. * Filters the absolute upload path for the WP installation. 
  1505. * 
  1506. * @since 1.2.0 
  1507. * 
  1508. * @param string $value Absolute upload path for the WP installation. 
  1509. */ 
  1510. return apply_filters( 'bp_core_avatar_upload_path', bp_core_get_upload_dir() ); 
  1511.  
  1512. /** 
  1513. * Get the raw base URL for root site upload location. 
  1514. * 
  1515. * @since 1.2.0 
  1516. * 
  1517. * @return string Full URL to current upload location. 
  1518. */ 
  1519. function bp_core_avatar_url() { 
  1520.  
  1521. /** 
  1522. * Filters the raw base URL for root site upload location. 
  1523. * 
  1524. * @since 1.2.0 
  1525. * 
  1526. * @param string $value Raw base URL for the root site upload location. 
  1527. */ 
  1528. return apply_filters( 'bp_core_avatar_url', bp_core_get_upload_dir( 'url' ) ); 
  1529.  
  1530. /** 
  1531. * Check if a given user ID has an uploaded avatar. 
  1532. * 
  1533. * @since 1.0.0 
  1534. * 
  1535. * @param int $user_id ID of the user whose avatar is being checked. 
  1536. * @return bool True if the user has uploaded a local avatar. Otherwise false. 
  1537. */ 
  1538. function bp_get_user_has_avatar( $user_id = 0 ) { 
  1539.  
  1540. if ( empty( $user_id ) ) 
  1541. $user_id = bp_displayed_user_id(); 
  1542.  
  1543. $retval = false; 
  1544. if ( bp_core_fetch_avatar( array( 'item_id' => $user_id, 'no_grav' => true, 'html' => false, 'type' => 'full' ) ) != bp_core_avatar_default( 'local' ) ) 
  1545. $retval = true; 
  1546.  
  1547. /** 
  1548. * Filters whether or not a user has an uploaded avatar. 
  1549. * 
  1550. * @since 1.6.0 
  1551. * 
  1552. * @param bool $retval Whether or not a user has an uploaded avatar. 
  1553. * @param int $user_id ID of the user being checked. 
  1554. */ 
  1555. return (bool) apply_filters( 'bp_get_user_has_avatar', $retval, $user_id ); 
  1556.  
  1557. /** 
  1558. * Utility function for fetching an avatar dimension setting. 
  1559. * 
  1560. * @since 1.5.0 
  1561. * 
  1562. * @param string $type Dimension type you're fetching dimensions for. 'thumb' 
  1563. * or 'full'. Default: 'thumb'. 
  1564. * @param string $h_or_w Which dimension is being fetched. 'height' or 'width'. 
  1565. * Default: 'height'. 
  1566. * @return int|bool $dim The dimension. 
  1567. */ 
  1568. function bp_core_avatar_dimension( $type = 'thumb', $h_or_w = 'height' ) { 
  1569. $bp = buddypress(); 
  1570. $dim = isset( $bp->avatar->{$type}->{$h_or_w} ) ? (int) $bp->avatar->{$type}->{$h_or_w} : false; 
  1571.  
  1572. /** 
  1573. * Filters the avatar dimension setting. 
  1574. * 
  1575. * @since 1.5.0 
  1576. * 
  1577. * @param int|bool $dim Dimension setting for the type. 
  1578. * @param string $type The type of avatar whose dimensions are requested. Default 'thumb'. 
  1579. * @param string $h_or_w The dimension parameter being requested. Default 'height'. 
  1580. */ 
  1581. return apply_filters( 'bp_core_avatar_dimension', $dim, $type, $h_or_w ); 
  1582.  
  1583. /** 
  1584. * Get the 'thumb' avatar width setting. 
  1585. * 
  1586. * @since 1.5.0 
  1587. * 
  1588. * @return int The 'thumb' width. 
  1589. */ 
  1590. function bp_core_avatar_thumb_width() { 
  1591.  
  1592. /** 
  1593. * Filters the 'thumb' avatar width setting. 
  1594. * 
  1595. * @since 1.5.0 
  1596. * 
  1597. * @param int $value Value for the 'thumb' avatar width setting. 
  1598. */ 
  1599. return apply_filters( 'bp_core_avatar_thumb_width', bp_core_avatar_dimension( 'thumb', 'width' ) ); 
  1600.  
  1601. /** 
  1602. * Get the 'thumb' avatar height setting. 
  1603. * 
  1604. * @since 1.5.0 
  1605. * 
  1606. * @return int The 'thumb' height. 
  1607. */ 
  1608. function bp_core_avatar_thumb_height() { 
  1609.  
  1610. /** 
  1611. * Filters the 'thumb' avatar height setting. 
  1612. * 
  1613. * @since 1.5.0 
  1614. * 
  1615. * @param int $value Value for the 'thumb' avatar height setting. 
  1616. */ 
  1617. return apply_filters( 'bp_core_avatar_thumb_height', bp_core_avatar_dimension( 'thumb', 'height' ) ); 
  1618.  
  1619. /** 
  1620. * Get the 'full' avatar width setting. 
  1621. * 
  1622. * @since 1.5.0 
  1623. * 
  1624. * @return int The 'full' width. 
  1625. */ 
  1626. function bp_core_avatar_full_width() { 
  1627.  
  1628. /** 
  1629. * Filters the 'full' avatar width setting. 
  1630. * 
  1631. * @since 1.5.0 
  1632. * 
  1633. * @param int $value Value for the 'full' avatar width setting. 
  1634. */ 
  1635. return apply_filters( 'bp_core_avatar_full_width', bp_core_avatar_dimension( 'full', 'width' ) ); 
  1636.  
  1637. /** 
  1638. * Get the 'full' avatar height setting. 
  1639. * 
  1640. * @since 1.5.0 
  1641. * 
  1642. * @return int The 'full' height. 
  1643. */ 
  1644. function bp_core_avatar_full_height() { 
  1645.  
  1646. /** 
  1647. * Filters the 'full' avatar height setting. 
  1648. * 
  1649. * @since 1.5.0 
  1650. * 
  1651. * @param int $value Value for the 'full' avatar height setting. 
  1652. */ 
  1653. return apply_filters( 'bp_core_avatar_full_height', bp_core_avatar_dimension( 'full', 'height' ) ); 
  1654.  
  1655. /** 
  1656. * Get the max width for original avatar uploads. 
  1657. * 
  1658. * @since 1.5.0 
  1659. * 
  1660. * @return int The max width for original avatar uploads. 
  1661. */ 
  1662. function bp_core_avatar_original_max_width() { 
  1663.  
  1664. /** 
  1665. * Filters the max width for original avatar uploads. 
  1666. * 
  1667. * @since 1.5.0 
  1668. * 
  1669. * @param int $value Value for the max width. 
  1670. */ 
  1671. return apply_filters( 'bp_core_avatar_original_max_width', (int) buddypress()->avatar->original_max_width ); 
  1672.  
  1673. /** 
  1674. * Get the max filesize for original avatar uploads. 
  1675. * 
  1676. * @since 1.5.0 
  1677. * 
  1678. * @return int The max filesize for original avatar uploads. 
  1679. */ 
  1680. function bp_core_avatar_original_max_filesize() { 
  1681.  
  1682. /** 
  1683. * Filters the max filesize for original avatar uploads. 
  1684. * 
  1685. * @since 1.5.0 
  1686. * 
  1687. * @param int $value Value for the max filesize. 
  1688. */ 
  1689. return apply_filters( 'bp_core_avatar_original_max_filesize', (int) buddypress()->avatar->original_max_filesize ); 
  1690.  
  1691. /** 
  1692. * Get the URL of the 'full' default avatar. 
  1693. * 
  1694. * @since 1.5.0 
  1695. * @since 2.6.0 Introduced `$params` and `$object_type` parameters. 
  1696. * 
  1697. * @param string $type 'local' if the fallback should be the locally-hosted version 
  1698. * of the mystery person, 'gravatar' if the fallback should be 
  1699. * Gravatar's version. Default: 'gravatar'. 
  1700. * @param array $params Parameters passed to bp_core_fetch_avatar(). 
  1701. * @return string The URL of the default avatar. 
  1702. */ 
  1703. function bp_core_avatar_default( $type = 'gravatar', $params = array() ) { 
  1704. // Local override. 
  1705. if ( defined( 'BP_AVATAR_DEFAULT' ) ) { 
  1706. $avatar = BP_AVATAR_DEFAULT; 
  1707.  
  1708. // Use the local default image. 
  1709. } elseif ( 'local' === $type ) { 
  1710. $size = ''; 
  1711. if ( 
  1712. ( isset( $params['type'] ) && 'thumb' === $params['type'] && bp_core_avatar_thumb_width() <= 50 ) || 
  1713. ( isset( $params['width'] ) && $params['width'] <= 50 ) 
  1714. ) { 
  1715.  
  1716. $size = '-50'; 
  1717.  
  1718. $avatar = buddypress()->plugin_url . "bp-core/images/mystery-man{$size}.jpg"; 
  1719.  
  1720. // Use Gravatar's mystery person as fallback. 
  1721. } else { 
  1722. $size = ''; 
  1723. if ( isset( $params['type'] ) && 'thumb' === $params['type'] ) { 
  1724. $size = bp_core_avatar_thumb_width(); 
  1725. } else { 
  1726. $size = bp_core_avatar_full_width(); 
  1727. $avatar = '//www.gravatar.com/avatar/00000000000000000000000000000000?d=mm&s=' . $size; 
  1728.  
  1729. /** 
  1730. * Filters the URL of the 'full' default avatar. 
  1731. * 
  1732. * @since 1.5.0 
  1733. * @since 2.6.0 Added `$params`. 
  1734. * 
  1735. * @param string $avatar URL of the default avatar. 
  1736. * @param array $params Params provided to bp_core_fetch_avatar(). 
  1737. */ 
  1738. return apply_filters( 'bp_core_avatar_default', $avatar, $params ); 
  1739.  
  1740. /** 
  1741. * Get the URL of the 'thumb' default avatar. 
  1742. * 
  1743. * Uses Gravatar's mystery-person avatar, unless BP_AVATAR_DEFAULT_THUMB has been 
  1744. * defined. 
  1745. * 
  1746. * @since 1.5.0 
  1747. * @since 2.6.0 Introduced `$object_type` parameter. 
  1748. * 
  1749. * @param string $type 'local' if the fallback should be the locally-hosted version 
  1750. * of the mystery person, 'gravatar' if the fallback should be 
  1751. * Gravatar's version. Default: 'gravatar'. 
  1752. * @param array $params Parameters passed to bp_core_fetch_avatar(). 
  1753. * @return string The URL of the default avatar thumb. 
  1754. */ 
  1755. function bp_core_avatar_default_thumb( $type = 'gravatar', $params = array() ) { 
  1756. // Local override. 
  1757. if ( defined( 'BP_AVATAR_DEFAULT_THUMB' ) ) { 
  1758. $avatar = BP_AVATAR_DEFAULT_THUMB; 
  1759.  
  1760. // Use the local default image. 
  1761. } elseif ( 'local' === $type ) { 
  1762. $avatar = buddypress()->plugin_url . 'bp-core/images/mystery-man-50.jpg'; 
  1763.  
  1764. // Use Gravatar's mystery person as fallback. 
  1765. } else { 
  1766. $avatar = '//www.gravatar.com/avatar/00000000000000000000000000000000?d=mm&s=' . bp_core_avatar_thumb_width(); 
  1767.  
  1768. /** 
  1769. * Filters the URL of the 'thumb' default avatar. 
  1770. * 
  1771. * @since 1.5.0 
  1772. * @since 2.6.0 Added `$params`. 
  1773. * 
  1774. * @param string $avatar URL of the default avatar. 
  1775. * @param string $params Params provided to bp_core_fetch_avatar(). 
  1776. */ 
  1777. return apply_filters( 'bp_core_avatar_thumb', $avatar, $params ); 
  1778.  
  1779. /** 
  1780. * Reset the week parameter of the WordPress main query if needed. 
  1781. * 
  1782. * When cropping an avatar, a $_POST['w'] var is sent, setting the 'week' 
  1783. * parameter of the WordPress main query to this posted var. To avoid 
  1784. * notices, we need to make sure this 'week' query var is reset to 0. 
  1785. * 
  1786. * @since 2.2.0 
  1787. * 
  1788. * @param WP_Query|null $posts_query The main query object. 
  1789. */ 
  1790. function bp_core_avatar_reset_query( $posts_query = null ) { 
  1791. $reset_w = false; 
  1792.  
  1793. // Group's avatar edit screen. 
  1794. if ( bp_is_group_admin_page() ) { 
  1795. $reset_w = bp_is_group_admin_screen( 'group-avatar' ); 
  1796.  
  1797. // Group's avatar create screen. 
  1798. } elseif ( bp_is_group_create() ) { 
  1799. /** 
  1800. * We can't use bp_get_groups_current_create_step(). 
  1801. * as it's not set yet 
  1802. */ 
  1803. $reset_w = 'group-avatar' === bp_action_variable( 1 ); 
  1804.  
  1805. // User's change avatar screen. 
  1806. } else { 
  1807. $reset_w = bp_is_user_change_avatar(); 
  1808.  
  1809. // A user or a group is cropping an avatar. 
  1810. if ( true === $reset_w && isset( $_POST['avatar-crop-submit'] ) ) { 
  1811. $posts_query->set( 'w', 0 ); 
  1812. add_action( 'bp_parse_query', 'bp_core_avatar_reset_query', 10, 1 ); 
  1813.  
  1814. /** 
  1815. * Checks whether Avatar UI should be loaded. 
  1816. * 
  1817. * @since 2.3.0 
  1818. * 
  1819. * @return bool True if Avatar UI should load, false otherwise. 
  1820. */ 
  1821. function bp_avatar_is_front_edit() { 
  1822. $retval = false; 
  1823.  
  1824. // No need to carry on if the current WordPress version is not supported. 
  1825. if ( ! bp_attachments_is_wp_version_supported() ) { 
  1826. return $retval; 
  1827.  
  1828. if ( bp_is_user_change_avatar() && 'crop-image' !== bp_get_avatar_admin_step() ) { 
  1829. $retval = ! bp_core_get_root_option( 'bp-disable-avatar-uploads' ); 
  1830.  
  1831. if ( bp_is_active( 'groups' ) ) { 
  1832. // Group creation. 
  1833. if ( bp_is_group_create() && bp_is_group_creation_step( 'group-avatar' ) && 'crop-image' !== bp_get_avatar_admin_step() ) { 
  1834. $retval = ! bp_disable_group_avatar_uploads(); 
  1835.  
  1836. // Group Manage. 
  1837. } elseif ( bp_is_group_admin_page() && bp_is_group_admin_screen( 'group-avatar' ) && 'crop-image' !== bp_get_avatar_admin_step() ) { 
  1838. $retval = ! bp_disable_group_avatar_uploads(); 
  1839.  
  1840. /** 
  1841. * Use this filter if you need to : 
  1842. * - Load the avatar UI for a component that is !groups or !user (return true regarding your conditions) 
  1843. * - Completely disable the avatar UI introduced in 2.3 (eg: __return_false()) 
  1844. * 
  1845. * @since 2.3.0 
  1846. * 
  1847. * @param bool $retval Whether or not to load the Avatar UI. 
  1848. */ 
  1849. return apply_filters( 'bp_avatar_is_front_edit', $retval ); 
  1850.  
  1851. /** 
  1852. * Checks whether the Webcam Avatar UI part should be loaded. 
  1853. * 
  1854. * @since 2.3.0 
  1855. * 
  1856. * @global $is_safari 
  1857. * @global $is_IE 
  1858. * 
  1859. * @return bool True to load the Webcam Avatar UI part. False otherwise. 
  1860. */ 
  1861. function bp_avatar_use_webcam() { 
  1862. global $is_safari, $is_IE, $is_chrome; 
  1863.  
  1864. /** 
  1865. * Do not use the webcam feature for mobile devices 
  1866. * to avoid possible confusions. 
  1867. */ 
  1868. if ( wp_is_mobile() ) { 
  1869. return false; 
  1870.  
  1871. /** 
  1872. * Bail when the browser does not support getUserMedia. 
  1873. * 
  1874. * @see http://caniuse.com/#feat=stream 
  1875. */ 
  1876. if ( $is_safari || $is_IE || ( $is_chrome && ! is_ssl() ) ) { 
  1877. return false; 
  1878.  
  1879. /** 
  1880. * Use this filter if you need to disable the webcam capture feature 
  1881. * by returning false. 
  1882. * 
  1883. * @since 2.3.0 
  1884. * 
  1885. * @param bool $value Whether or not to load Webcam Avatar UI part. 
  1886. */ 
  1887. return apply_filters( 'bp_avatar_use_webcam', true ); 
  1888.  
  1889. /** 
  1890. * Template function to load the Avatar UI javascript templates. 
  1891. * 
  1892. * @since 2.3.0 
  1893. */ 
  1894. function bp_avatar_get_templates() { 
  1895. if ( ! bp_avatar_is_front_edit() ) { 
  1896. return; 
  1897.  
  1898. bp_attachments_get_template_part( 'avatars/index' ); 
  1899.  
  1900. /** 
  1901. * Trick to check if the theme's BuddyPress templates are up to date. 
  1902. * 
  1903. * If the "avatar templates" are not including the new template tag, this will 
  1904. * help users to get the avatar UI. 
  1905. * 
  1906. * @since 2.3.0 
  1907. */ 
  1908. function bp_avatar_template_check() { 
  1909. if ( ! bp_avatar_is_front_edit() ) { 
  1910. return; 
  1911.  
  1912. if ( ! did_action( 'bp_attachments_avatar_check_template' ) ) { 
  1913. bp_attachments_get_template_part( 'avatars/index' ); 
.