<?php

class PeepSoProfilePreferencesAjax extends PeepSoAjaxCallback
{
	// @todo docblock
	public function savepreference(PeepSoAjaxResponse $resp)
	{
		$view_uid 	= $this->_input->int('view_user_id',0);
		$uid 		= $this->_input->int('user_id',0);
		$cur_uid	= get_current_user_id();

	    // create a user instance for this user
        $user = PeepSoUser::get_instance($cur_uid);
        $data = $user->get_peepso_user();

		if( (!$view_uid || !$uid || !$cur_uid) || ($cur_uid != $uid) || ($view_uid !=$uid && !current_user_can('edit_users')) ) {
			$resp->error('Insufficient permissions');
			$resp->success(FALSE);
			return;
		}

		$meta_key    = $this->_input->value('meta_key', '', FALSE); // SQL Safe
		$new_value   = $this->_input->raw('value');

		// TODO : check if meta key is from user meta or peepso_user table
		if($meta_key == 'usr_profile_acc') {
			$data['usr_profile_acc'] = (isset($new_value)) ? $new_value : PeepSo::ACCESS_MEMBERS;

			// update the peepso_user table with the post data
			$success = $user->update_peepso_user($data);

		// Only allow writing user-meta keys that PeepSo actually exposes as
		// editable preferences. The previous behaviour gated on a bare "peepso_"
		// prefix, which let any logged-in user write ANY internal peepso_* meta
		// key (e.g. peepso_name_based_avatar_path -> arbitrary file deletion, or
		// peepso_ban_user_date -> self-unban). See PeepSo/PeepSo#8138.
		} else if (in_array($meta_key, $this->get_allowed_preference_keys(), TRUE)) {
			$old_value	= get_user_meta($cur_uid, $meta_key, true );
			$success = FALSE;
			if($old_value !== $new_value) {
				// will return false if the previous value is the same as $new_value
				$success = update_user_meta( $cur_uid, $meta_key, $new_value );
			}

		} else {
			$success = FALSE;
		}

		if( TRUE === $success || is_int($success) ) {
			$resp->notice(__('Preferences saved.', 'peepso-core'));
			$resp->set('count', $success);
			$resp->success($success);
		} else {
			$resp->success( FALSE );
			$resp->error(__('Failed to save changes.', 'peepso-core'));
		}
	}

	/**
	 * Allowlist of user-meta keys that savepreference() is permitted to write.
	 *
	 * Derived from the live preferences definition so it always matches the exact
	 * set of options PeepSo and its modules actually render as user-editable — the
	 * same source of truth the form is built from, including keys contributed by
	 * add-ons through the 'peepso_profile_preferences' filter (chat, EDD,
	 * WooCommerce, AweCommerce, ...). This replaces the old bare "peepso_" prefix
	 * check, which let any logged-in user write arbitrary internal peepso_* meta.
	 * See PeepSo/PeepSo#8138.
	 *
	 * @return string[]
	 */
	private function get_allowed_preference_keys()
	{
		$keys = array('usr_profile_acc');

		$definition = PeepSoProfile::get_instance()->get_preferences_definition();

		if (is_array($definition)) {
			foreach ($definition as $group) {
				if (empty($group['items']) || !is_array($group['items'])) {
					continue;
				}
				foreach ($group['items'] as $key => $field) {
					$keys[] = $key;
				}
			}
		}

		/**
		 * Filter the preference keys savepreference() may write. Modules that add
		 * a preference outside the standard definition can register its key here.
		 *
		 * @param string[] $keys Allowed user-meta keys.
		 */
		$keys = apply_filters('peepso_savepreference_allowed_keys', array_values(array_unique($keys)));

		return (is_array($keys) ? $keys : array());
	}

	// @todo docblock
	public function save_notifications(PeepSoAjaxResponse $resp)
	{
		$view_uid 	= $this->_input->int('view_user_id',0);
		$uid 		= $this->_input->int('user_id',0);
		$cur_uid	= get_current_user_id();

	    // create a user instance for this user
        $user = PeepSoUser::get_instance($cur_uid);
        $data = $user->get_peepso_user();

		if( (!$view_uid || !$uid || !$cur_uid) || ($cur_uid != $uid) || ($view_uid !=$uid && !current_user_can('edit_users')) ) {
			$resp->error('Insufficient permissions');
			$resp->success(FALSE);
			return;
		}

		// get existing un-checklist notification
		$peepso_notifications = get_user_meta($cur_uid, 'peepso_notifications');
		$notifications = ($peepso_notifications) ? $peepso_notifications[0] : array();

        $fieldname	= $this->_input->value('fieldname', '', FALSE); // SQL Safe
        $new_value	= $this->_input->int('value');

        $extra_fieldname = $this->_input->value('fieldname_extra', '', FALSE); // SQL Safe
        $extra_new_value 	= $this->_input->int('value_extra');




        if('email_intensity' == $fieldname) {
            // #7094 When the admin forces the intensity on everyone, the front-end control is
            // disabled; reject any write here too so a crafted request cannot bypass the lock.
            if(PeepSo::get_option('lock_email_intensity')) {
                $resp->error(__('This setting is managed by the site administrator.', 'peepso-core'));
                $resp->success(FALSE);
                return;
            }
            $success = update_user_meta($cur_uid, 'peepso_email_intensity', $new_value);
        } elseif('web_push' == $fieldname) {
            $success = update_user_meta($cur_uid, 'peepso_web_push', $new_value);
        } elseif('peepso_email_digest_receive_enabled' == $fieldname) {
            $success = update_user_meta($cur_uid, 'peepso_email_digest_receive_enabled', $new_value);
        } elseif('peepso_brute_force_email_receive_enabled' == $fieldname) {
            $success = update_user_meta($cur_uid, 'peepso_brute_force_email_receive_enabled', $new_value);
        } else {
            $override = apply_filters('peepso_save_notifications', $fieldname);

            if (1 === $new_value) {
                $key = array_search($fieldname, $notifications);
                unset($notifications[$key]);
            } else {
                $notifications[] = $fieldname;
            }

            if(strlen($extra_fieldname)) {
                $extra_override = apply_filters('peepso_save_notifications', $extra_fieldname);

                if (1 === $extra_new_value) {
                    $key = array_search($extra_fieldname, $notifications);
                    unset($notifications[$key]);
                } else {
                    $notifications[] = $extra_fieldname;
                }
            }

            // will return false if the previous value is the same as $existing_unchecked
            $success = update_user_meta($cur_uid, 'peepso_notifications', $notifications);
        }

        if (TRUE === $success || is_int($success)) {
            $resp->notice(__('Preferences saved', 'peepso-core'));
            $resp->set('count', $success);
            $resp->success($success);
        } else {
            $resp->success(FALSE);
            $resp->error(__('Failed to save', 'peepso-core'));
        }

	}
}

// EOF
