Sindbad~EG File Manager
<?php
class PeepSoField
{
const USER_META_FIELD_KEY = 'peepso_user_field_';
// user
protected $wp_user;
protected $user_id;
// field
public $id;
public $desc;
public $default_desc;
public $key;
public $title;
public $published;
public $value;
public $old_value;
public $admin_registration_only = 0; // enables the "registration only" option for admins
public $admin_only;
public $acc;
public $can_acc;
public $data_type = NULL;
// rendering
public $input_args = array();
public $meta;
// Admin label (readable "type")
public static $admin_label='Field';
// AVAILABLE render methods - these are listed for the Administrator to choose from
public $render_methods = array('_render'=>'default (text)');
public $render_form_methods = array();
// Flag for fields, is render in registration page?
public static $profile_field_prefix = "profile_field_";
public $is_registration_page = FALSE;
public $el_class = 'ps-input';
// AVAILABLE validation methods - these are listed for the Administrator to choose from
// All fields have an optional "required" validation rule, and can extend it with more options
public $validation_methods = array(
'required',
);
// postmeta related to the field objects
protected $field_meta_keys = array(
// rendering
'is_core', // INT 1,2 (optional) 1 - WP core, 2 - PeepSo
'order', // INT
'class', // string
'method', // string
'method_form', // string
'validation', // JSON object (optional) how to validate
'searchable', // INT 0,1
'privacywarning', // INT 0,1
'privacywarningtext', // STRING
// user flags
'half_width', // INT 0,1 half width on registration
'user_registration', // INT 0,1 visible on registration
'user_disable_edit', // INT 0,1 readonly
'user_disable_guest_view', // INT 0,1 hide on profiles
'user_disable_acc', // INT 0,1 disable privacy
// extra flags
'default_acc', // INT default privacy level
'admin_registration_only', // INT 0,1 lets admin enable the registration only mode
'user_registration_only', // INT 0,1 field only shows in registration and is not counted in field stats
'admin_only', // INT 0,1 only admin users can see it
'user_admin_editable_only', // INT 0,1 only admin users can see it
'user_admin_visible_only', // INT 0,1 only admin users can see it
);
// which postmeta has to be forced INT
// all INTs default to ZERO
protected $as_int = array(
'is_core',
'order',
'default_acc',
'half_width',
'user_registration',
'user_disable_edit',
'user_disable_guest_view',
'user_disable_acc',
'admin_registration_only',
'user_registration_only',
'admin_only',
'user_admin_editable_only',
'user_admin_visible_only',
);
// which postmeta should be deserialized
protected $as_array = array(
'validation',
);
#public $profile_fields = array();
// validation
public $validation_errors = array();
/**
* Get the wp_posts ID of a given field
*/
public static function get_field_by_id( $id, $user_id = NULL)
{
if(is_numeric($id)) {
$post = get_post($id);
} elseif(strlen($id)) {
$args = array(
'post_type' => trim(PeepSoField::USER_META_FIELD_KEY,'_'),
'name' => $id,
);
$q = new WP_Query($args);
if($q->have_posts()) {
$post = $q->next_post();
}
}
if(!isset($post)) {
return( FALSE );
}
return self::get_field_by_post($post, $user_id);
}
/**
* Decide which sub-class of PeepSoField* should handle the given field
*/
public static function get_field_by_post( $post, $user_id = NULL )
{
$class = 'PeepSoField'.get_post_meta($post->ID, 'class', TRUE);
if(!class_exists($class)) {
return NULL;
}
return new $class($post, $user_id);
}
public function __construct( $post , $user_id = NULL )
{
// fallback in case someone passed an entire user object
if($user_id instanceof WP_User) {
$user_id = $user_id->ID;
}
$this->user_id = (NULL != $user_id) ? $user_id : get_current_user_id();
$this->_get_wp_user();
$id = $post->ID;
// the core fields are identified by name eg USER_META_FIELD_KEY_gender
// custom added ones are referred by id eg USER_META_FIELD_KEY_2137
// custom added fields post_name is same as ID
$key = $post->post_name;
$this->id = $id;
$this->default_desc = __('Enter data', 'peepso-core');
$this->input_args['name'] = PeepSoField::$profile_field_prefix . $id;
$this->input_args['id'] = PeepSoField::$profile_field_prefix . $id;
$this->input_args['data_id'] = $id;
$this->key = PeepSoField::user_meta_key_add($key);
$this->title = html_entity_decode($post->post_title);
$this->desc = $post->post_content;
$this->published = ('publish' == $post->post_status) ? 1 : 0;
// load up all field meta
$this->meta = (object)array();
$this->field_meta_keys = apply_filters('peepso_user_field_meta_keys', $this->field_meta_keys);
$this->as_int = apply_filters('peepso_user_field_meta_keys_as_int', $this->as_int);
$this->as_array = apply_filters('peepso_user_field_meta_keys_as_array', $this->as_array);
foreach ($this->field_meta_keys as $meta) {
// default - don't deserialize, string
$is_int = FALSE; // if TRUE - don't deserialize, force int
$is_array = FALSE; // if TRUE - deserialize
if (in_array($meta, $this->as_int)) {
$is_int = TRUE;
}
if (in_array($meta, $this->as_array)) {
$is_array = TRUE;
}
$this->meta->$meta = get_post_meta($id, $meta, TRUE);
// intval('') might return 1, need to do this manually
if (TRUE == $is_int) {
if (strlen($this->meta->$meta)) {
$this->meta->$meta = intval($this->meta->$meta);
} else {
$this->meta->$meta = 0;
}
continue;
}
if (TRUE == $is_array) {
$this->meta->$meta = (object)$this->meta->$meta;
}
if('privacywarningtext' == $meta && !strlen($this->meta->$meta)) {
$this->meta->$meta = __('Stay safe! Be careful about disclosing personal information.','peepso-core');
}
}
// values used in front-end rendering
$this->value = $this->get_value(FALSE);
$this->acc = $this->get_acc();
$this->can_acc = PeepSoUser::is_accessible_static($this->prop('acc'), $this->prop('user_id'));
if(!current_user_can('edit_users') && 1 == $this->prop('meta', 'user_admin_visible_only')) {
$this->can_acc = 0;
}
// Additional accessibility conditions for non-owners and non-admins
if ($this->user_id != get_current_user_id() && !current_user_can('edit_users')) {
// Guest view disabled (eg first name, last name)
if (1 == $this->prop('meta', 'user_disable_guest_view')) {
$this->can_acc = 0;
}
// The field is empty
if ((!is_array($this->value) && !strlen($this->value) && !$this->value) || (is_array($this->value) && !$this->value)) {
$this->can_acc = 0;
}
}
if(0 == $this->prop('meta','is_core')) {
$this->admin_registration_only = 1;
$this->admin_only = 1;
}
}
/** GET & SET **/
/**
* Return any usermeta, with privacy check
* @since 1.6
* @reason Custom Profile Fields
*
* @param string $key the meta key
* @param bool|TRUE $check_acc whether to perform privacy check
* @return bool|mixed
*/
public function get_value($check_acc = TRUE)
{
$key = $this->key;
$this->_get_wp_user();
if(TRUE === $check_acc && !PeepSoUser::is_accessible_static($this->get_acc(), $this->user_id)) {
return FALSE;
}
// if called externally, the value might already be initialized
if(FALSE != $this->value) {
return $this->value;
}
// we are usually handling internal PeepSo meta here
$key = PeepSoField::user_meta_key_add($key);
if (isset($this->wp_user->$key)) {
return ($this->wp_user->$key);
}
// fallback 1: to WordPress defaults
$key = PeepSoField::user_meta_key_trim($key);
if (isset($this->wp_user->$key)) {
return ($this->wp_user->$key);
}
// fallback 2: to legacy value
$ret_legacy = $this->get_legacy_field_value($check_acc);
if(add_user_meta($this->user_id, PeepSoField::user_meta_key_add($key), $ret_legacy, true)) {
return $ret_legacy;
}
return FALSE;
}
public function save($value, $validate_only = FALSE)
{
if( 'array' == $this->data_type && !is_array($value) ) {
if( $value_array = json_decode(stripslashes(html_entity_decode($value)), TRUE)) {
$value = $value_array;
} else {
$value = array();
}
}
$this->old_value = $this->value;
$this->value = $value;
if ($this->validate()) {
if ($validate_only) {
return (TRUE);
} else {
if($this->set_user_field($this->key, $this->value)) {
do_action('peepso_action_profile_field_save', $this);
return(TRUE);
}
}
}
return (FALSE);
}
public function save_acc($acc)
{
$this->acc=$acc;
return $this->set_user_field($this->key.'_acc', $acc);
}
/**
* Save any valid user meta
*
* @param string $key
* @param string $value
* @return bool|int
*/
public function set_user_field($key, $value)
{
$wp_key = PeepSoField::user_meta_key_trim($key);
$key = PeepSoField::user_meta_key_add($key);
$is_core = isset($this->meta->is_core) ? $this->meta->is_core : 0;
// use ints for the _acc fields
if (substr($key, -4) == '_acc') {
$value = intval($value);
$is_core = 0;
}
// some values are stored in WP itself
if(1 == $is_core) {
return wp_update_user(array('ID' => $this->user_id, $wp_key => $value));
}
// otherwise put in PeepSo keys
if( $value == get_user_meta($this->user_id, $key, true) ) {
return TRUE;
}
return update_user_meta($this->user_id, $key, $value);
}
/**
* Provides fallback if PeepSo has been freshly upgraded
* Will pull data from legacy peepso_users columns and copy them over to the new meta keys
*
* @param string $key
* @param bool|TRUE $check_acc
* @return bool|mixed
*/
protected function get_legacy_field_value($check_acc = TRUE)
{
$this->_get_wp_user();
$col_name = 'usr_' . $this->key;
$acc_name = $col_name . '_acc'; // name of access column in peepso_users table
if ($check_acc) {
// if there's an access column, check it
// $this->user->peepso_user is NOT a typo
if (isset($this->user->peepso_user[$acc_name])) {
if (!$this->user->is_accessible($this->key))
return (FALSE);
}
}
if (isset($this->wp_user->{$this->key})) {
return ($this->wp_user->{$this->key});
}
return (FALSE);
}
/** UTILS **/
/**
* Make sure $this->wp_user is properly set-up
*/
protected function _get_wp_user()
{
if( FALSE == $this->wp_user) {
$this->wp_user = get_user_by('id', $this->user_id);
}
}
/** VALIDATION & ACCESS **/
public function validate()
{
if( count((array) $this->meta->validation) ) {
if( 1 == $this->prop('meta','validation','required') ) {
$test = new PeepSoFieldTestRequired($this->value);
$test->test();
if (NULL !== $test->error) {
$this->validation_errors['required'] = $test->error;
return FALSE;
}
}
if(isset($this->meta->validation->required) && !$this->is_registration_page) {
unset($this->meta->validation->required);
}
if(is_object($this->meta->validation) && count((array) $this->meta->validation)) {
foreach ($this->meta->validation as $rule => $args) {
if (0 == $args) {
// this validation option is disabled
continue;
}
$classname = 'PeepSoFieldTest' . ucfirst($rule);
// the "value" keys will automatically be skipped because the class doesnt exist
if (class_exists($classname)) {
$value_key = $rule . '_value';
if ($this->prop('meta', 'validation', $value_key)) {
$args = $this->prop('meta', 'validation', $value_key);
}
$test = new $classname($this->value, $args);
$test->test();
if (NULL !== $test->error) {
$this->validation_errors[$rule] = $test->error;
}
}
}
}
if($this->prop('meta','user_admin_editable_only') && !PeepSo::is_admin()) {
$this->validation_errors['user_admin_editable_only'] = 'Only administrator can edit this field';
}
if(count($this->validation_errors)) {
return FALSE;
}
}
return TRUE;
}
public function get_acc()
{
$this->_get_wp_user();
$key_acc = PeepSoField::user_meta_key_add($this->key).'_acc';
$default = $this->prop('meta','default_acc');
if(0 == $default) {
$default = PeepSo::ACCESS_MEMBERS;
}
add_user_meta($this->user_id, $key_acc, $default, TRUE);
// Searchable fields default to Site Members
if(1 == $this->prop('meta', 'searchable')) {
return PeepSo::ACCESS_MEMBERS;
}
if(1 == $this->prop('meta','user_disable_acc')) {
return $default;
}
if (isset($this->wp_user->$key_acc) && 0 < intval($this->wp_user->$key_acc)) {
return ($this->wp_user->$key_acc);
} else {
return $default;
}
return FALSE;
}
/**
* Attach self::meta_field_key to the key
*
* @param string $key
* @return string
*/
public static function user_meta_key_add( $key )
{
return self::USER_META_FIELD_KEY . self::user_meta_key_trim( $key );
}
/**
* Trim self::meta_field_key from the key
*
* @param string $key
* @return string
*/
public static function user_meta_key_trim( $key )
{
return str_ireplace(self::USER_META_FIELD_KEY, '', $key);
}
/**
* Renderers are protected
* They have to be interfaced via render() and render_input()
* They also have to be accessible from child classes
*/
/** RENDER the front-end (user profile/edit/registration) **/
/**
* @param string $context - view|register|edit
*/
public function should_render( $context = 'view' )
{
if( !$this->can_acc ) {
return FALSE;
}
$key = 'user_'.$context;
if(isset($this->meta->$key)) {
// In profile view, even empty fields render (if they are accessible) so they can be modified
if('view' == $context) {
return (1 == $this->meta->$key) ? TRUE : FALSE;
}
// Fields in different context (eg on_cover) don't render if they are empty
return ( $this->value ) ? TRUE : FALSE;
}
return TRUE;
}
public function render_input($echo = true)
{
// check if loaded in registration or not
$method_form = $this->prop('meta','method_form');
if(TRUE === $this->is_registration_page) {
$method_form = $method_form . '_register';
}
$ret = call_user_func(array($this, $method_form));
if($echo) {
echo $ret;
}
return $ret;
}
public function render($echo = TRUE)
{
$ret = call_user_func(array($this, $this->prop('meta','method')));
if($echo) {
echo $ret;
}
return $ret;
}
public function render_validation( $echo = TRUE )
{
ob_start();
$has_validation_options = 0;
$validation_config = (array)$this->prop('meta','validation');
foreach($this->validation_methods as $method) {
if(1 == $this->prop('meta','validation',$method)){
$validation_class = 'PeepSoFieldTest'.$method;
if('required' == $method || !class_exists($validation_class)) {
continue;
}
$test = new $validation_class(0,0);
$has_validation_options++;
/**
* @todo this HTML block must be identified by $method
*
* if the AJAX response has $method key in errors:
* highlight this HTML block RED
* and DO NOT display the error again on the bottom
*
* however if AJAX response has a $method that was NOT printed here
* DO display the error on the bottom, and do nothing her
*/
echo '<div class="ps-alert ps-alert--sm ps-alert--neutral ps-js-validation ps-js-validation-' . esc_attr($method) . '">';
echo wp_kses_post(sprintf($test->message, $this->prop('meta','validation',$method.'_value')));
echo '</div>';
}
}
$ret = ob_get_clean();
if($echo) {
echo wp_kses_post($ret);
}
return $ret;
}
protected function _render()
{
if(empty($this->value) || ($this->is_registration_page)) {
return $this->_render_empty_fallback();
}
return $this->value;
}
protected function _render_empty_fallback()
{
ob_start();
#6610
$override = apply_filters('peepso_field_render_empty_fallback', $this);
if(!is_object($override) && strlen($override)) {
echo wp_kses_post($override);
return ob_get_clean();
}
if(!$this->is_registration_page){
?>
<span class="ps-profile__about-field-placeholder <?php echo ( 1 == $this->prop('meta','validation','required' ) ) ? 'ps-text--danger' : '';?>">
<?php echo wp_kses_post(__($this->prop('desc'), 'peepso-core')); ?>
</span>
<?php
} else {
echo wp_kses_post(__($this->prop('desc'), 'peepso-core'));
}
return ob_get_clean();
}
protected function _render_input_args()
{
ob_start();
echo ' name="'.esc_attr($this->input_args['name']).'"',
' id="'.esc_attr($this->input_args['id']).'"',
' data-id="'.esc_attr($this->id).'"';
return ob_get_clean();
}
protected function _render_required_args()
{
$required = '';
if( count((array) $this->meta->validation) ) {
if( 1 == $this->prop('meta','validation','required') ) {
$required = ' required';
}
}
return $required;
}
protected function _render_input_register_args()
{
ob_start();
echo ' name="'.esc_attr($this->input_args['name']).'"',
' id="'.esc_attr($this->input_args['id']).'"',
' data-id="'.esc_attr($this->id).'"';
if (!empty($this->el_class )) {
echo ' class="'.esc_attr($this->el_class).'"';
}
return ob_get_clean();
}
protected function _render_input_args_acc()
{
ob_start();
echo ' name="'.esc_attr($this->input_args['name']).'_acc"',
' id="'.esc_attr($this->input_args['id']).'_acc"',
' data-id="'.esc_attr($this->id).'"';
return ob_get_clean();
}
protected function _render_form_input( )
{
$ret = '<div class="ps-input__wrapper">';
$ret .= '<input class="ps-input ps-input--sm ps-input--count" type="text" value="' . $this->value . '"' . $this->_render_input_args() . $this->_render_required_args() . '>';
$ret .= '<div class="ps-form__chars-count ps-js-counter" style="display:none"></div>';
$ret .= '</div>';
return $ret;
}
protected function _render_form_input_register( )
{
// since key event not used in registration page
$ret = '<div class="ps-input__wrapper">';
$ret .= '<input class="ps-input ps-input--sm ps-input--count" type="text" value="' . $this->value . '"' . $this->_render_input_register_args() . $this->_render_required_args() . '>';
$ret .= '<div class="ps-form__chars-count ps-js-counter" style="display:none"></div>';
$ret .= '</div>';
return $ret;
}
public function render_access()
{
$acc = $this->acc;
if(FALSE == $acc) {
return FALSE;
}
$acc = intval($acc);
$privacy = PeepSoPrivacy::get_instance();
$access_settings = $privacy->get_access_settings();
if (!isset($access_settings[$acc])) {
// access value not found in keys, assume value from first access entry
$keys = array_keys($access_settings);
$acc = $keys[0];
}
if( 1 == $this->meta->user_disable_acc) {
?>
<div class="ps-profile__about-field-edit-item ps-tip ps-tip--arrow ps-tip--md" aria-label="<?php echo esc_attr(__('Some fields privacy is defined by the administrators', 'peepso-core')); ?>">
<span class="ps-btn ps-btn--xs ps-btn--app ps-btn--disabled">
<i class="<?php echo esc_attr($access_settings[$acc]['icon']);?>"></i><span class="ps-privacy-title"><?php echo esc_attr($access_settings[$acc]['label']);?></span>
</span>
</div>
<?php
return;
}
if( 1 == $this->prop('meta','searchable')) { ?>
<div class="ps-profile__about-field-edit-item ps-tip ps-tip--arrow ps-tip--md" aria-label="<?php echo esc_attr(__('Some fields privacy is defined by the administrators', 'peepso-core')); ?>">
<span class="ps-btn ps-btn--xs ps-btn--app ps-btn--app ps-btn--disabled">
<i class="<?php echo esc_attr($access_settings[$acc]['icon']);?>"></i><span class="ps-privacy-title"><?php echo esc_attr($access_settings[$acc]['label']);?></span>
</span>
</div>
<?php
return;
}
?>
<div class="ps-profile__about-field-edit-item ps-profile-privacy">
<div class="ps-dropdown ps-dropdown--menu ps-privacy-dropdown ps-js-dropdown">
<input type="hidden" <?php echo wp_kses_post($this->_render_input_args_acc());?> value="<?php echo wp_kses_post($acc);?>" />
<button id="acc-<?php echo esc_attr($this->input_args['name']);?>" type="button"
class="ps-btn ps-btn--xs ps-btn--app ps-dropdown__toggle ps-js-dropdown-toggle"
aria-label="<?php echo esc_attr(__('Edit privacy of ' . $this->title, 'peepso-core')); ?>">
<span class="dropdown-value"><i class="<?php echo esc_attr($access_settings[$acc]['icon']);?>"></i></span> <span class="ps-privacy-title"><?php echo esc_attr($access_settings[$acc]['label']);?></span>
</button>
<div class="ps-dropdown__menu ps-js-dropdown-menu">
<?php foreach ($access_settings as $acc_key => $acc_value) { ?>
<a href="#" id="<?php echo esc_attr($this->id . '-acc-' . $acc_key) ?>" data-option-value="<?php echo wp_kses_post($acc_key); ?>" onclick="profile.change_privacy(this); return false;">
<i class="<?php echo esc_attr($acc_value['icon']); ?>"></i>
<span><?php echo esc_attr($acc_value['label']); ?></span>
</a>
<?php } ?>
</div>
</div>
</div>
<?php
}
public function prop($key, $key1=NULL, $key2=NULL)
{
// chain validate each key
if(!isset($this->$key)) {
return FALSE;
}
if('meta' == $key && !isset($this->$key->$key1)) {
#echo "$key1 not set";
return;
}
if($key1 && !isset($this->$key->$key1)) {
return FALSE;
}
if($key2 && !isset($this->$key->$key1->$key2)) {
return FALSE;
}
// reverse return
if($key2) {
return $this->$key->$key1->$key2;
}
if($key1) {
return $this->$key->$key1;
}
return $this->$key;
}
}
// EOF
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists