/bp-xprofile-custom-fields-type.php

  1. <?php 
  2. /** 
  3. Plugin Name: BuddyPress Xprofile Custom Fields Type 
  4. Plugin URI: http://donmik.com/en/buddypress-xprofile-custom-fields-type/ 
  5. Description: BuddyPress installation required!! This plugin add custom field types to BuddyPress Xprofile extension. Field types are: Birthdate, Email, Url, Datepicker, ... 
  6. Version: 2.6.3 
  7. Author: donmik 
  8. Author URI: http://donmik.com 
  9. */ 
  10. if (!class_exists('Bxcft_Plugin')) 
  11. class Bxcft_Plugin 
  12. CONST BXCFT_MAX_FILESIZE = 8; 
  13.  
  14. private $version; 
  15. private $user_id = null; 
  16. private $images_ext_allowed; 
  17. private $images_max_filesize; 
  18. private $files_ext_allowed; 
  19. private $files_max_filesize; 
  20. private $fields_type_with_select2; 
  21. private $fields_type_multiple; 
  22.  
  23. private $autolink_filter_removed = false; 
  24.  
  25. private $bxcft_field_types = array( 
  26. 'birthdate' => 'Bxcft_Field_Type_Birthdate',  
  27. 'email' => 'Bxcft_Field_Type_Email',  
  28. 'web' => 'Bxcft_Field_Type_Web',  
  29. 'datepicker' => 'Bxcft_Field_Type_Datepicker',  
  30. 'select_custom_post_type' => 'Bxcft_Field_Type_SelectCustomPostType',  
  31. 'multiselect_custom_post_type' => 'Bxcft_Field_Type_MultiSelectCustomPostType',  
  32. 'select_custom_taxonomy' => 'Bxcft_Field_Type_SelectCustomTaxonomy',  
  33. 'multiselect_custom_taxonomy' => 'Bxcft_Field_Type_MultiSelectCustomTaxonomy',  
  34. 'checkbox_acceptance' => 'Bxcft_Field_Type_CheckboxAcceptance',  
  35. 'image' => 'Bxcft_Field_Type_Image',  
  36. 'file' => 'Bxcft_Field_Type_File',  
  37. 'color' => 'Bxcft_Field_Type_Color',  
  38. 'decimal_number' => 'Bxcft_Field_Type_DecimalNumber',  
  39. 'number_minmax' => 'Bxcft_Field_Type_NumberMinMax',  
  40. 'slider' => 'Bxcft_Field_Type_Slider',  
  41. ); 
  42.  
  43. public function __construct () 
  44. $this->version = "2.6"; 
  45.  
  46. /** Main hooks **/ 
  47. add_action( 'plugins_loaded', array($this, 'bxcft_update') ); 
  48.  
  49. /** Admin hooks **/ 
  50. add_action( 'admin_init', array($this, 'admin_init') ); 
  51. add_action( 'admin_notices', array($this, 'admin_notices') ); 
  52.  
  53. /** Buddypress hook **/ 
  54. add_action( 'bp_init', array($this, 'init') ); 
  55. add_action( 'bp_signup_validate', array($this, 'bxcft_signup_validate') ); 
  56. add_action( 'xprofile_data_before_save', array($this, 'bxcft_xprofile_data_before_save') ); 
  57. add_action( 'xprofile_data_after_delete', array($this, 'bxcft_xprofile_data_after_delete') ); 
  58.  
  59. /** Select2 fields */ 
  60. add_action( 'xprofile_field_after_submitbox', array($this, 'bxcft_show_select2_box') ); 
  61. add_action( 'xprofile_fields_saved_field', array($this, 'bxcft_save_do_select2') ); 
  62. add_action( 'bp_custom_profile_edit_fields_pre_visibility', array($this, 'bxcft_enable_select2_field') ); 
  63.  
  64. /** Filters **/ 
  65. add_filter( 'bp_xprofile_get_field_types', array($this, 'bxcft_get_field_types'), 10, 1 ); 
  66. add_filter( 'xprofile_get_field_data', array($this, 'bxcft_get_field_data'), 10, 2 ); 
  67. add_filter( 'bp_get_the_profile_field_value', array($this, 'bxcft_remove_autolink_filter_from_buddypress'), 7, 2); 
  68. add_filter( 'bp_get_the_profile_field_value', array($this, 'bxcft_get_field_value'), 10, 3); 
  69. add_filter( 'bp_get_the_profile_field_value', array($this, 'bxcft_restore_autolink_filter_from_buddypress'), 11, 2); 
  70. add_filter( 'bxcft_do_autolink', array($this, 'bxcft_enabled_autolink'), 10, 1 ); 
  71. /** BP Profile Search Filters **/ 
  72. add_filter( 'bps_field_validation_type', array($this, 'bxcft_standard_fields_validation_type' ) ); 
  73. add_filter( 'bps_field_type_for_search_form', array($this, 'bxcft_standard_fields_type_for_search_form' ) ); 
  74. add_filter( 'bps_field_type_for_query', array($this, 'bxcft_standard_fields_for_query' ) ); 
  75. // Special fields. 
  76. add_filter( 'bps_field_validation', array($this, 'bxcft_special_fields_search_validation' ), 10, 2); 
  77. add_filter( 'bps_field_data_for_search_form', array($this, 'bxcft_special_fields_data_for_search_form' ) ); 
  78. add_filter( 'bps_field_query', array($this, 'bxcft_special_fields_query' ), 10, 4); 
  79. // Pre validate multiselect custom taxonomy. 
  80. add_filter( 'bp_xprofile_set_field_data_pre_validate', array( $this, 'bxcft_xprofile_set_field_data_pre_validate' ), 10, 3 ); 
  81.  
  82. public function init() 
  83. $this->images_ext_allowed = apply_filters('bxcft_images_ext_allowed', array( 
  84. 'jpg', 'jpeg', 'gif', 'png' 
  85. )); 
  86. $this->images_max_filesize = apply_filters('bxcft_images_max_filesize', Bxcft_Plugin::BXCFT_MAX_FILESIZE); 
  87. $this->files_ext_allowed = apply_filters('bxcft_files_ext_allowed', array( 
  88. 'doc', 'docx', 'pdf' 
  89. )); 
  90. $this->files_max_filesize = apply_filters('bxcft_files_max_filesize', Bxcft_Plugin::BXCFT_MAX_FILESIZE); 
  91. $this->fields_type_with_select2 = apply_filters('bxcft_field_types_with_select2', array( 
  92. 'selectbox', 'multiselectbox', 'select_custom_post_type',  
  93. 'multiselect_custom_post_type', 'select_custom_taxonomy',  
  94. 'multiselect_custom_taxonomy' 
  95. )); 
  96. $this->fields_type_multiple = apply_filters('bxcft_field_types_multiple', array( 
  97. 'multiselectbox', 'multiselect_custom_post_type',  
  98. 'multiselect_custom_taxonomy' 
  99. )); 
  100.  
  101. /** Includes **/ 
  102. if ( bp_is_active( 'xprofile' ) ) { 
  103. require_once( 'classes/Bxcft_Field_Type_Birthdate.php' ); 
  104. require_once( 'classes/Bxcft_Field_Type_Email.php' ); 
  105. require_once( 'classes/Bxcft_Field_Type_Web.php' ); 
  106. require_once( 'classes/Bxcft_Field_Type_Datepicker.php' ); 
  107. require_once( 'classes/Bxcft_Field_Type_SelectCustomPostType.php' ); 
  108. require_once( 'classes/Bxcft_Field_Type_MultiSelectCustomPostType.php' ); 
  109. require_once( 'classes/Bxcft_Field_Type_SelectCustomTaxonomy.php' ); 
  110. require_once( 'classes/Bxcft_Field_Type_MultiSelectCustomTaxonomy.php' ); 
  111. require_once( 'classes/Bxcft_Field_Type_CheckboxAcceptance.php' ); 
  112. require_once( 'classes/Bxcft_Field_Type_Image.php' ); 
  113. require_once( 'classes/Bxcft_Field_Type_File.php' ); 
  114. require_once( 'classes/Bxcft_Field_Type_Color.php' ); 
  115. require_once( 'classes/Bxcft_Field_Type_DecimalNumber.php' ); 
  116. require_once( 'classes/Bxcft_Field_Type_NumberMinMax.php' ); 
  117. require_once( 'classes/Bxcft_Field_Type_Slider.php' ); 
  118.  
  119. if (bp_is_user_profile_edit() || bp_is_register_page()) { 
  120. $this->load_js(); 
  121.  
  122. public function load_js() { 
  123. wp_enqueue_script('bxcft-modernizr', plugin_dir_url(__FILE__) . 'js/modernizr.js', array(), '2.6.2', false); 
  124. wp_enqueue_script('bxcft-jscolor', plugin_dir_url(__FILE__) . 'js/jscolor/jscolor.js', array(), '1.4.1', true); 
  125. wp_enqueue_script('bxcft-public', plugin_dir_url(__FILE__) . 'js/public.js', array('jquery'), $this->version, true); 
  126.  
  127. // Select 2. 
  128. wp_enqueue_script('bxcft-select2', plugin_dir_url(__FILE__) . 'js/select2/select2.min.js', array('jquery'), '4.0.2', true); 
  129. $locale = get_locale(); 
  130. if (file_exists(plugin_dir_path(__FILE__) . 'js/select2/i18n/' . $locale . '.js')) { 
  131. wp_enqueue_script('bxcft-select2-i18n', plugin_dir_url(__FILE__) . 'js/select2/i18n/' . get_locale() . '.js', array('bxcft-select2'), '4.0.2', true); 
  132. wp_enqueue_style('bxcft-select2', plugin_dir_url(__FILE__) . 'css/select2/select2.min.css', array(), '4.0.2'); 
  133.  
  134. public function admin_init() 
  135. if (is_admin() && get_option('bxcft_activated') == 1) { 
  136. // Check if BuddyPress 2.5 is installed. 
  137. $version_bp = array( '0' ); 
  138. if (function_exists('is_plugin_active') && is_plugin_active('buddypress/bp-loader.php')) { 
  139. // BuddyPress loaded. 
  140. $version_bp = get_file_data( WP_PLUGIN_DIR . '/buddypress/bp-loader.php', array( 'Version' ) ); 
  141. if ( ! $this->compare_versions( array_pop( $version_bp ), '2.5' ) ) { 
  142. $notices = get_option('bxcft_notices'); 
  143. $notices[] = __('BuddyPress Xprofile Custom Fields Type plugin needs <b>BuddyPress 2.5</b>, please install or upgrade BuddyPress.', 'bxcft'); 
  144. update_option('bxcft_notices', $notices); 
  145. delete_option('bxcft_activated'); 
  146. else if ( ! bp_is_active( 'xprofile' ) ) { 
  147. $notices = get_option('bxcft_notices'); 
  148. $notices[] = __('BuddyPress Xprofile Custom Fields Type plugin needs Buddypress Xprofile Component. Please enable Xprofile first.', 'bxcft'); 
  149. update_option('bxcft_notices', $notices); 
  150. delete_option('bxcft_activated'); 
  151.  
  152. // Enqueue javascript. 
  153. wp_enqueue_script('bxcft-js', plugin_dir_url(__FILE__) . 'js/admin.js', array(), $this->version, false); 
  154. wp_localize_script('bxcft-js', 'fields_type_with_select2', array('types' => $this->fields_type_with_select2)); 
  155.  
  156. if (isset($_GET['page']) && $_GET['page'] === 'bp-profile-edit') { 
  157. $this->load_js(); 
  158.  
  159. /** 
  160. * Compare buddypress version with needed version. 
  161. * 
  162. * @since 2.6 
  163. * 
  164. * @param Array $version_actual Actual version. 
  165. * @param Array $version_needed Needed version. 
  166. * @return boolean 
  167. */ 
  168. private function compare_versions( $version_actual, $version_needed ) { 
  169. $components_version_actual = explode( '.', $version_actual ); 
  170. $components_version_needed = explode( '.', $version_needed ); 
  171.  
  172. foreach ( $components_version_needed as $key => $element ) { 
  173. if ( isset( $components_version_actual[ $key ] ) && 
  174. (int) $components_version_actual[ $key ] < (int) $element ) { 
  175. return false; 
  176.  
  177. return true; 
  178.  
  179. public function admin_notices() 
  180. $notices = get_option('bxcft_notices'); 
  181. if ($notices) { 
  182. foreach ($notices as $notice) 
  183. echo "<div class='error'><p>$notice</p></div>"; 
  184. delete_option('bxcft_notices'); 
  185.  
  186. public function bxcft_get_field_types($fields) 
  187. $fields = array_merge($fields, $this->bxcft_field_types); 
  188. return $fields; 
  189.  
  190. /** 
  191. * Remove `xprofile_filter_link_profile_data` on `bp_get_the_profile_field_value` 
  192. * 
  193. * @since 2.4.6 
  194. * @param mixed $value Value of field 
  195. * @return mixed Same value of field 
  196. */ 
  197. public function bxcft_remove_autolink_filter_from_buddypress($value, $type='') { 
  198. if (in_array($type, array_keys($this->bxcft_field_types)) 
  199. && !Bxcft_Plugin::is_autolink_filter_removed()) { 
  200. $this->autolink_filter_removed = true; 
  201. remove_filter( 'bp_get_the_profile_field_value',  
  202. 'xprofile_filter_link_profile_data', 9 ); 
  203.  
  204. return $value; 
  205.  
  206. /** 
  207. * Restore `xprofile_filter_link_profile_data` on `bp_get_the_profile_field_value` 
  208. * 
  209. * @since 2.4.6 
  210. * @param mixed $value Value of field 
  211. * @return mixed Same value of field 
  212. */ 
  213. public function bxcft_restore_autolink_filter_from_buddypress($value, $type='') { 
  214. if ($this->autolink_filter_removed) { 
  215. add_filter( 'bp_get_the_profile_field_value',  
  216. 'xprofile_filter_link_profile_data', 9, 3 ); 
  217.  
  218. return $value; 
  219.  
  220. /** 
  221. * Check if autolink is enabled. If it is enabled for this type of field and 
  222. * if it was removed or it isn't removed by the user in functions.php. 
  223. * 
  224. * @since 2.4.6 
  225. * @param boolean $do_autolink Actual value of do_autolink 
  226. * @return boolean Filtered value of do_autolink 
  227. */ 
  228. public function bxcft_enabled_autolink($do_autolink) { 
  229. return ($do_autolink && 
  230. ($this->autolink_filter_removed 
  231. || !Bxcft_Plugin::is_autolink_filter_removed())); 
  232.  
  233. /** 
  234. * This method is now useless, it will be removed on version 3.0. 
  235. * 
  236. * @since 2.4.6 
  237. * @param mixed $value Value of field 
  238. * @param int $field_id Id of field 
  239. * @return mixed Same value of field 
  240. */ 
  241. public function bxcft_get_field_data($value, $field_id) 
  242. $field = BP_XProfile_Field::get_instance($field_id); 
  243. if (!$field) { 
  244. return; 
  245.  
  246. /** 
  247. * @deprecated 3.0 This filter will be removed in version 3.0. Please 
  248. * stop using it, use instead 'bxcft_TYPENAME_display_filter' 
  249. */ 
  250. return apply_filters('bxcft_show_field_value', $value, $field->type,  
  251. $field_id, $value); 
  252.  
  253. /** 
  254. * This method is now useless, it will be removed on version 3.0. 
  255. * 
  256. * @since 2.4.6 
  257. * @param mixed $value Value of field 
  258. * @param int $field_id Id of field 
  259. * @param string $type Type of field 
  260. * @return mixed Same value of field 
  261. */ 
  262. public function bxcft_get_field_value($value='', $type='', $id='') 
  263. /** 
  264. * @deprecated 3.0 This filter will be removed in version 3.0. Please 
  265. * stop using it, use instead 'bxcft_TYPENAME_display_filter' 
  266. */ 
  267. return apply_filters('bxcft_show_field_value', $value, $type, $id, $value); 
  268.  
  269. /** 
  270. * Returns the folder where files and images will be saved. 
  271. * 
  272. * @since 2.4.6 
  273. * @param integer $user_id Id of current displayed user. 
  274. * @return array array of upload_dir 
  275. */ 
  276. public function bxcft_profile_upload_dir( $user_id = 0 ) 
  277. if ($user_id == 0 && empty($this->user_id)) 
  278. $this->user_id = bp_displayed_user_id(); 
  279.  
  280. /** 
  281. * bxcft_upload_dir 
  282. * 
  283. * Use this filter if you want to change the folder 
  284. * where files and images are saved. 
  285. * 
  286. * @since 2.4.6 
  287. * @var string 
  288. */ 
  289. $profile_subdir = apply_filters( 'bxcft_upload_dir', '/profiles/' . $this->user_id,  
  290. $this->user_id); 
  291.  
  292. $upload_dir = array( 
  293. 'path' => bp_core_get_upload_dir() . $profile_subdir,  
  294. 'url' => bp_core_get_upload_dir('url') . $profile_subdir,  
  295. 'subdir' => bp_core_get_upload_dir() . $profile_subdir,  
  296. 'basedir' => bp_core_get_upload_dir() . $profile_subdir,  
  297. 'baseurl' => bp_core_get_upload_dir('url') . $profile_subdir,  
  298. 'error' => false,  
  299. ); 
  300.  
  301. return apply_filters( 'bxcft_profile_upload_dir', $upload_dir ); 
  302.  
  303. public function bxcft_signup_validate() 
  304. global $bp; 
  305. if ( bp_is_active( 'xprofile' ) ) 
  306. if ( isset( $_POST['signup_profile_field_ids'] ) && !empty( $_POST['signup_profile_field_ids'] ) ) 
  307. $profile_field_ids = explode(', ', $_POST['signup_profile_field_ids']); 
  308. foreach ($profile_field_ids as $field_id) 
  309. $field = new BP_XProfile_Field($field_id); 
  310. if ( ($field->type == 'image' || $field->type == 'file') && 
  311. isset($_FILES['field_'.$field_id])) { 
  312. // Delete required field error. 
  313. unset($bp->signup->errors['field_'.$field_id]); 
  314.  
  315. $filesize = round($_FILES['field_'.$field_id]['size'] / (1024 * 1024), 2); 
  316. if ($field->is_required && $filesize <= 0) { 
  317. $bp->signup->errors['field_' . $field_id] = __( 'This is a required field', 'buddypress' ); 
  318. } elseif ($filesize > 0) { 
  319. // Check extensions. 
  320. $ext = strtolower(substr($_FILES['field_'.$field_id]['name'], strrpos($_FILES['field_'.$field_id]['name'], '.')+1)); 
  321. if ($field->type == 'image') { 
  322. if (!in_array($ext, $this->images_ext_allowed)) { 
  323. $bp->signup->errors['field_'.$field_id] = sprintf(__('Image type not allowed: (%s).', 'bxcft'), implode(', ', $this->images_ext_allowed)); 
  324. elseif ($filesize > $this->images_max_filesize) { 
  325. $bp->signup->errors['field_'.$field_id] = sprintf(__('Max image upload size: %s MB.', 'bxcft'), $this->images_max_filesize); 
  326. } elseif ($field->type == 'file') { 
  327. if (!in_array($ext, $this->files_ext_allowed)) { 
  328. $bp->signup->errors['field_'.$field_id] = sprintf(__('File type not allowed: (%s).', 'bxcft'), implode(', ', $this->files_ext_allowed)); 
  329. elseif ($filesize > $this->files_max_filesize) { 
  330. $bp->signup->errors['field_'.$field_id] = sprintf(__('Max file upload size: %s MB.', 'bxcft'), $this->files_max_filesize); 
  331. elseif ($field->type == 'checkbox_acceptance' && $field->is_required) { 
  332. if (isset($_POST['field_' . $field_id]) 
  333. && $_POST['field_' . $field_id] != 1) { 
  334. $bp->signup->errors['field_' . $field_id] = __( 'This is a required field', 'buddypress' ); 
  335. elseif ($field->type == 'birthdate') { 
  336. $max_age = 0; 
  337. $options = $field->get_children(); 
  338. foreach ($options as $o) { 
  339. if ($o->name != 'show_age' && $o->name != 'show_birthdate') { 
  340. $max_age = (int)$o->name; 
  341. break; 
  342.  
  343. if ($max_age > 0) { 
  344. // Check birthdate. 
  345. if (class_exists(DateTime)) { 
  346. $now = new DateTime(); 
  347. $birthdate = new DateTime(sprintf("%s-%s-%s",  
  348. $_POST['field_'.$field_id.'_year'],  
  349. $_POST['field_'.$field_id.'_month'],  
  350. $_POST['field_'.$field_id.'_day'])); 
  351. $age = $now->diff($birthdate); 
  352. if ($age->y < $max_age) { 
  353. $bp->signup->errors['field_' . $field_id] = sprintf(__( 'You have to be at least %s years old.', 'bxcft' ), $max_age); 
  354. } // End foreach... 
  355. } // End if ( isset... 
  356. } // End if ( bp_is_active(... 
  357.  
  358. function bxcft_xprofile_data_before_save($data) 
  359. global $bp; 
  360.  
  361. $field_id = $data->field_id; 
  362. $field = new BP_XProfile_Field($field_id); 
  363.  
  364. if ($field->type == 'image' || $field->type == 'file' && isset($_FILES['field_'.$field_id])) 
  365. $uploads = wp_upload_dir(); 
  366. $filesize = round($_FILES['field_'.$field_id]['size'] / (1024 * 1024), 2); 
  367. if (isset($_FILES['field_'.$field_id]) && $filesize > 0) 
  368. $ext = strtolower(substr($_FILES['field_'.$field_id]['name'], strrpos($_FILES['field_'.$field_id]['name'], '.')+1)); 
  369. if ($field->type == 'image') 
  370. $ext_allowed = $this->images_ext_allowed; 
  371. if (!in_array($ext, $ext_allowed)) 
  372. bp_core_add_message( sprintf(__('Image type not allowed: (%s).', 'bxcft'), implode(', ', $this->images_ext_allowed)), 'error' ); 
  373. bp_core_redirect( trailingslashit( bp_displayed_user_domain() . $bp->profile->slug . '/edit/group/' . bp_action_variable( 1 ) ) ); 
  374. elseif ($filesize > $this->images_max_filesize) { 
  375. bp_core_add_message( sprintf(__('Max image upload size: %s MB.', 'bxcft'), $this->images_max_filesize), 'error' ); 
  376. bp_core_redirect( trailingslashit( bp_displayed_user_domain() . $bp->profile->slug . '/edit/group/' . bp_action_variable( 1 ) ) ); 
  377. } else { 
  378. // Delete previous image. 
  379. if (isset($_POST['field_'.$field_id.'_hiddenimg']) && 
  380. !empty($_POST['field_'.$field_id.'_hiddenimg']) && 
  381. file_exists($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenimg'])) 
  382. unlink($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenimg']); 
  383. elseif ($field->type == 'file') 
  384. $ext_allowed = $this->files_ext_allowed; 
  385. if (!in_array($ext, $ext_allowed)) { 
  386. bp_core_add_message( sprintf(__('File type not allowed: (%s).', 'bxcft'), implode(', ', $this->files_ext_allowed)), 'error' ); 
  387. bp_core_redirect( trailingslashit( bp_displayed_user_domain() . $bp->profile->slug . '/edit/group/' . bp_action_variable( 1 ) ) ); 
  388. elseif ($filesize > $this->files_max_filesize) { 
  389. bp_core_add_message( sprintf(__('Max file upload size: %s MB.', 'bxcft'), $this->files_max_filesize), 'error' ); 
  390. bp_core_redirect( trailingslashit( bp_displayed_user_domain() . $bp->profile->slug . '/edit/group/' . bp_action_variable( 1 ) ) ); 
  391. } else { 
  392. // Delete previous file. 
  393. if (isset($_POST['field_'.$field_id.'_hiddenfile']) && 
  394. !empty($_POST['field_'.$field_id.'_hiddenfile']) && 
  395. file_exists($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenfile'])) 
  396. unlink($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenfile']); 
  397.  
  398. if (in_array($ext, $ext_allowed)) 
  399. require_once( ABSPATH . '/wp-admin/includes/file.php' ); 
  400. $this->user_id = $data->user_id; 
  401. add_filter( 'upload_dir', array($this, 'bxcft_profile_upload_dir'), 10, 0 ); 
  402. $_POST['action'] = 'wp_handle_upload'; 
  403. $uploaded_file = wp_handle_upload( $_FILES['field_'.$field_id] ); 
  404. remove_filter('upload_dir', array($this, 'bxcft_profile_upload_dir'), 10 ); 
  405. $value = str_replace($uploads['baseurl'], '', $uploaded_file['url']); 
  406. } else { 
  407. // Handles delete checkbox. 
  408. if ($field->type == 'image' && isset($_POST['field_'.$field_id.'_deleteimg']) && 
  409. $_POST['field_'.$field_id.'_deleteimg']) 
  410. if (isset($_POST['field_'.$field_id.'_hiddenimg']) && 
  411. !empty($_POST['field_'.$field_id.'_hiddenimg']) && 
  412. file_exists($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenimg'])) 
  413. unlink($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenimg']); 
  414. $value = array(); 
  415. elseif ($field->type == 'image') 
  416. $value = (isset($_POST['field_'.$field_id.'_hiddenimg'])) ? 
  417. $_POST['field_'.$field_id.'_hiddenimg'] : ''; 
  418.  
  419. if ($field->type == 'file' && isset($_POST['field_'.$field_id.'_deletefile']) && 
  420. $_POST['field_'.$field_id.'_deletefile']) 
  421. if (isset($_POST['field_'.$field_id.'_hiddenfile']) && 
  422. !empty($_POST['field_'.$field_id.'_hiddenfile']) && 
  423. file_exists($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenfile'])) 
  424. unlink($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenfile']); 
  425. $value = array(); 
  426. elseif ($field->type == 'file') 
  427. $value = isset($_POST['field_'.$field_id.'_hiddenfile']) ? 
  428. $_POST['field_'.$field_id.'_hiddenfile'] : ''; 
  429.  
  430. $data->value = (isset($value))?$value:''; 
  431. elseif ($field->type == 'birthdate') { 
  432. $max_age = 0; 
  433. $options = $field->get_children(); 
  434. foreach ($options as $o) { 
  435. if ($o->name != 'show_age' && $o->name != 'show_birthdate') { 
  436. $max_age = (int)$o->name; 
  437. break; 
  438.  
  439. if ($max_age > 0) { 
  440. // Check birthdate. 
  441. if (class_exists(DateTime)) { 
  442. $now = new DateTime(); 
  443. $birthdate = new DateTime(sprintf("%s-%s-%s",  
  444. $_POST['field_'.$field_id.'_year'],  
  445. $_POST['field_'.$field_id.'_month'],  
  446. $_POST['field_'.$field_id.'_day'])); 
  447. $age = $now->diff($birthdate); 
  448. if ($age->y < $max_age) { 
  449. bp_core_add_message( sprintf(__( 'You have to be at least %s years old.', 'bxcft' ), $max_age), 'error' ); 
  450. bp_core_redirect( trailingslashit( bp_displayed_user_domain() . $bp->profile->slug . '/edit/group/' . bp_action_variable( 1 ) ) ); 
  451.  
  452. public function bxcft_xprofile_data_after_delete($data) 
  453. $field_id = $data->field_id; 
  454. $field = new BP_XProfile_Field($field_id); 
  455. $uploads = wp_upload_dir(); 
  456. if ($field->type == 'image' && isset($_POST['field_'.$field_id.'_deleteimg']) && 
  457. $_POST['field_'.$field_id.'_deleteimg']) 
  458. if (isset($_POST['field_'.$field_id.'_hiddenimg']) && 
  459. !empty($_POST['field_'.$field_id.'_hiddenimg']) && 
  460. file_exists($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenimg'])) 
  461. unlink($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenimg']); 
  462.  
  463. if ($field->type == 'file' && isset($_POST['field_'.$field_id.'_deletefile']) && 
  464. $_POST['field_'.$field_id.'_deletefile']) 
  465. if (isset($_POST['field_'.$field_id.'_hiddenfile']) && 
  466. !empty($_POST['field_'.$field_id.'_hiddenfile']) && 
  467. file_exists($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenfile'])) 
  468. unlink($uploads['basedir'] . $_POST['field_'.$field_id.'_hiddenfile']); 
  469.  
  470. public function bxcft_xprofile_set_field_data_pre_validate( $value, $field, $field_type_obj ) { 
  471. if ($field->type === 'multiselect_custom_taxonomy') { 
  472. $options = $field->get_children(); 
  473. $allow_new_tags = false; 
  474. $taxonomy_selected = ''; 
  475. foreach ($options as $option) { 
  476. if ( Bxcft_Field_Type_MultiSelectCustomTaxonomy::ALLOW_NEW_TAGS === $option->name) { 
  477. $allow_new_tags = true; 
  478. } else { 
  479. $taxonomy_selected = $option->name; 
  480.  
  481. if ( $allow_new_tags && ! empty( $taxonomy_selected ) ) { 
  482. // Add new tags if needed. 
  483. $value_to_return = array(); 
  484. foreach ( $value as $tag ) { 
  485. if ( ! term_exists( (int) $tag, $taxonomy_selected ) && 
  486. ! term_exists( $tag, $taxonomy_selected ) ) { 
  487. // Create tag. 
  488. $res = wp_insert_term( $tag, $taxonomy_selected ); 
  489. if (is_array($res)) { 
  490. $value_to_return[] = "{$res['term_id']}"; 
  491. } else { 
  492. $value_to_return[] = $tag; 
  493. } else { 
  494. $value_to_return[] = $tag; 
  495. } else { 
  496. $value_to_return = $value; 
  497. } else { 
  498. $value_to_return = $value; 
  499.  
  500. return $value_to_return; 
  501.  
  502. public function bxcft_standard_fields_validation_type($field_type) 
  503. switch($field_type) { 
  504. case 'birthdate': 
  505. // Search by age. 
  506. $field_type = 'datebox'; 
  507. break; 
  508.  
  509. case 'email': 
  510. case 'web': 
  511. $field_type = 'textbox'; 
  512. break; 
  513.  
  514. case 'number_minmax': 
  515. case 'slider': 
  516. $field_type = 'number'; 
  517. break; 
  518.  
  519. return $field_type; 
  520.  
  521. public function bxcft_standard_fields_for_query($field_type) { 
  522. switch($field_type) { 
  523. case 'birthdate': 
  524. case 'datepicker': 
  525. // Search by age. 
  526. $field_type = 'datebox'; 
  527. break; 
  528.  
  529. case 'email': 
  530. case 'web': 
  531. case 'color': 
  532. case 'decimal_number': 
  533. $field_type = 'textbox'; 
  534. break; 
  535.  
  536. case 'number_minmax': 
  537. case 'slider': 
  538. $field_type = 'number'; 
  539. break; 
  540.  
  541. case 'select_custom_post_type': 
  542. case 'select_custom_taxonomy': 
  543. $field_type = 'selectbox'; 
  544. break; 
  545.  
  546. case 'multiselect_custom_post_type': 
  547. case 'multiselect_custom_taxonomy': 
  548. $field_type = 'multiselectbox'; 
  549. break; 
  550.  
  551. case 'checkbox_acceptance': 
  552. $field_type = 'radio'; 
  553. break; 
  554.  
  555. return $field_type; 
  556.  
  557. public function bxcft_standard_fields_type_for_search_form($field_type) { 
  558. switch($field_type) { 
  559. case 'birthdate': 
  560. case 'datepicker': 
  561. // Search by age. 
  562. $field_type = 'datebox'; 
  563. break; 
  564.  
  565. case 'email': 
  566. case 'web': 
  567. case 'color': 
  568. case 'decimal_number': 
  569. $field_type = 'textbox'; 
  570. break; 
  571.  
  572. case 'number_minmax': 
  573. case 'slider': 
  574. $field_type = 'number'; 
  575. break; 
  576.  
  577. return $field_type; 
  578.  
  579. public function bxcft_special_fields_search_validation($settings, $field) { 
  580. list($value, $description, $range) = $settings; 
  581. switch ($field->type) { 
  582. case 'decimal_number': 
  583. $range = true; 
  584. break; 
  585.  
  586. case 'datepicker': 
  587. case 'select_custom_post_type': 
  588. case 'multiselect_custom_post_type': 
  589. case 'select_custom_taxonomy': 
  590. case 'multiselect_custom_taxonomy': 
  591. case 'checkbox_acceptance': 
  592. case 'image': 
  593. case 'file': 
  594. case 'color': 
  595. $range = false; 
  596. break; 
  597.  
  598. return array($value, $description, $range); 
  599.  
  600. public function bxcft_special_fields_data_for_search_form($f) { 
  601. $request = stripslashes_deep ($_REQUEST); 
  602. switch ($f->type) { 
  603. case 'select_custom_post_type': 
  604. case 'multiselect_custom_post_type': 
  605. $f->values = isset ($request[$f->code])? (array)$request[$f->code]: array (); 
  606. $field = new BP_XProfile_Field($f->id); 
  607. $array_options = array(); 
  608. if ($field) { 
  609. $childs = $field->get_children(); 
  610. if (isset($childs) && $childs && count($childs) > 0 
  611. && is_object($childs[0])) { 
  612. $post_type_selected = $childs[0]->name; 
  613. $posts = new WP_Query(array( 
  614. 'posts_per_page' => -1,  
  615. 'post_type' => $post_type_selected,  
  616. 'orderby' => 'title',  
  617. 'order' => 'ASC' 
  618. )); 
  619. if ($posts) { 
  620. foreach ($posts->posts as $p) { 
  621. $array_options[$p->ID] = $p->post_title; 
  622. $f->options = $array_options; 
  623. if ($f->type === 'select_custom_post_type') { 
  624. $f->display = 'selectbox'; 
  625. } else { 
  626. $f->display = 'multiselectbox'; 
  627. break; 
  628.  
  629. case 'select_custom_taxonomy': 
  630. case 'multiselect_custom_taxonomy': 
  631. $f->values = isset ($request[$f->code])? (array)$request[$f->code]: array (); 
  632. $field = new BP_XProfile_Field($f->id); 
  633. $array_options = array(); 
  634. if ($field) { 
  635. $childs = $field->get_children(); 
  636. if (isset($childs) && $childs && count($childs) > 0 
  637. && is_object($childs[0])) { 
  638. $taxonomy_selected = $childs[0]->name; 
  639. $terms = get_terms($taxonomy_selected, array( 
  640. 'hide_empty' => false 
  641. )); 
  642. if ($terms) { 
  643. foreach ($terms as $t) { 
  644. $array_options[$t->term_id] = $t->name; 
  645. $f->options = $array_options; 
  646. if ($f->type === 'select_custom_taxonomy') { 
  647. $f->display = 'selectbox'; 
  648. } else { 
  649. $f->display = 'multiselectbox'; 
  650. break; 
  651.  
  652. case 'checkbox_acceptance': 
  653. $f->values = isset ($request[$f->code])? (array)$request[$f->code]: array (); 
  654. $f->options = array( 
  655. 0 => __('no', 'bxcft'),  
  656. 1 => __('yes', 'bxcft') 
  657. ); 
  658. $f->display = 'radio'; 
  659. break; 
  660.  
  661. case 'image': 
  662. case 'file': 
  663. $f->values = isset ($request[$f->code])? (array)$request[$f->code]: array (); 
  664. $f->options = array( 
  665. 1 => __('Not empty', 'bxcft') 
  666. ); 
  667. $f->display = 'checkbox'; 
  668. break; 
  669.  
  670. return $f; 
  671.  
  672. public function bxcft_special_fields_query($results, $field, $key, $value) { 
  673. global $bp, $wpdb; 
  674. switch ($field->type) { 
  675. case 'image': 
  676. case 'file': 
  677. $sql = $wpdb->prepare ("SELECT user_id FROM {$bp->profile->table_name_data} WHERE field_id = %d AND value != ''", $field->id); 
  678. $results = $wpdb->get_col ($sql); 
  679. break; 
  680.  
  681. return $results; 
  682.  
  683. public function bxcft_show_select2_box($field) { 
  684. $do_select2 = bp_xprofile_get_meta( $field->id, 'field', 'do_select2'); 
  685. $hidden = true; 
  686. if (in_array($field->type, $this->fields_type_with_select2)) { 
  687. $hidden = false; 
  688. ?> 
  689. <div id="select2-box" class="postbox<?php if ($hidden): ?> hidden<?php endif; ?>"> 
  690. <h2><?php esc_html_e('Select2', 'bxft'); ?></h2> 
  691. <div class="inside"> 
  692. <p class="description">Enable select2 javascript code.</p> 
  693.  
  694. <p> 
  695. <label for="do-select2" class="screen-reader-text">Select2 status for this field</label> 
  696. <select name="do_select2" id="do-select2"> 
  697. <option value="on" <?php if ($do_select2 === 'on'): ?> selected="selected"<?php endif; ?>>Enabled</option> 
  698. <option value=""<?php if ($do_select2 !== 'on'): ?> selected="selected"<?php endif; ?>>Disabled</option> 
  699. </select> 
  700. </p> 
  701. </div> 
  702. </div> 
  703. <?php 
  704.  
  705. public function bxcft_save_do_select2($field) { 
  706. $field_id = $field->id; 
  707.  
  708. if (!in_array($field->type, $this->fields_type_with_select2)) { 
  709. bp_xprofile_update_field_meta($field_id, 'do_select2', '' ); 
  710. return; 
  711.  
  712. // Save select2 settings. 
  713. if ( 1 != $field_id ) { 
  714. if ( isset( $_POST['do_select2'] ) && 'on' === wp_unslash( $_POST['do_select2'] ) ) { 
  715. bp_xprofile_update_field_meta( $field_id, 'do_select2', 'on' ); 
  716. } else { 
  717. bp_xprofile_update_field_meta( $field_id, 'do_select2', 'off' ); 
  718.  
  719. public function bxcft_enable_select2_field() { 
  720. global $field; 
  721.  
  722. if (!in_array($field->type, $this->fields_type_with_select2)) { 
  723. return; 
  724.  
  725. $do_select2 = bp_xprofile_get_meta($field->id, 'field', 'do_select2'); 
  726. if ($do_select2 === 'on') { 
  727. $field_name_id = bp_get_the_profile_field_input_name(); 
  728. if (in_array($field->type, $this->fields_type_multiple)) { 
  729. $field_name_id .= '[]'; 
  730.  
  731. $allow_new_tags = false; 
  732. $options = $field->get_children(); 
  733. foreach ($options as $option) { 
  734. if (Bxcft_Field_Type_MultiSelectCustomTaxonomy::ALLOW_NEW_TAGS === $option->name) { 
  735. $allow_new_tags = true; 
  736.  
  737. if ($allow_new_tags) { 
  738. ?> 
  739. <script> 
  740. jQuery(function($) { 
  741. $('select[name="<?php echo $field_name_id; ?>"]').select2({ 
  742. tags: true,  
  743. tokenSeparators: [', '] 
  744. }); 
  745. }); 
  746. </script> 
  747. <?php 
  748. } else { 
  749. ?> 
  750. <script> 
  751. jQuery(function($) { 
  752. $('select[name="<?php echo $field_name_id; ?>"]').select2(); 
  753. }); 
  754. </script> 
  755. <?php 
  756.  
  757. public function bxcft_update() 
  758. $locale = apply_filters( 'bxcft_load_load_textdomain_get_locale', get_locale() ); 
  759. if ( !empty( $locale ) ) { 
  760. $mofile_default = sprintf( '%slang/%s.mo', plugin_dir_path(__FILE__), $locale ); 
  761. $mofile = apply_filters( 'bxcft_load_textdomain_mofile', $mofile_default ); 
  762.  
  763. if ( file_exists( $mofile ) ) { 
  764. load_textdomain( "bxcft", $mofile ); 
  765.  
  766. if (!get_option('bxcft_activated')) { 
  767. add_option('bxcft_activated', 1); 
  768. if (!get_option('bxcft_notices')) { 
  769. add_option('bxcft_notices'); 
  770.  
  771. /** 
  772. * Returns true if autolink filter is removed,  
  773. * false if it exists. 
  774. * 
  775. * @since 2.4.6 
  776. * @return boolean 
  777. */ 
  778. public static function is_autolink_filter_removed() { 
  779. return !(has_filter('bp_get_the_profile_field_value',  
  780. 'xprofile_filter_link_profile_data', 9)); 
  781.  
  782. public static function activate() 
  783. add_option('bxcft_activated', 1); 
  784. add_option('bxcft_notices', array()); 
  785.  
  786. public static function deactivate() 
  787. delete_option('bxcft_activated'); 
  788. delete_option('bxcft_notices'); 
  789.  
  790. if (class_exists('Bxcft_Plugin')) { 
  791. register_activation_hook(__FILE__, array('Bxcft_Plugin', 'activate')); 
  792. register_deactivation_hook(__FILE__, array('Bxcft_Plugin', 'deactivate')); 
  793. $bxcft_plugin = new Bxcft_Plugin(); 
.