Begin XenForo Sync and continue Uploader
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build:submissions-uploader": "vite build --config vite-configs/vite.submissions-uploader.config.js",
|
||||||
"build:rhpz-url": "vite build --config vite-configs/vite.rhpz-url.config.js",
|
"build:rhpz-url": "vite build --config vite-configs/vite.rhpz-url.config.js",
|
||||||
"build:send-notification": "vite build --config vite-configs/vite.send-notification.config.js",
|
"build:send-notification": "vite build --config vite-configs/vite.send-notification.config.js",
|
||||||
"build:manage-notifications": "vite build --config vite-configs/vite.manage-notifications.config.js",
|
"build:manage-notifications": "vite build --config vite-configs/vite.manage-notifications.config.js",
|
||||||
|
|||||||
@@ -181,6 +181,26 @@ class Settings extends Abstract_Page {
|
|||||||
'discord',
|
'discord',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
add_settings_section(
|
||||||
|
'xf',
|
||||||
|
__( 'XenForo', 'romhackplaza' ),
|
||||||
|
function(){},
|
||||||
|
'romhackplaza-config'
|
||||||
|
);
|
||||||
|
|
||||||
|
add_settings_field(
|
||||||
|
'xf_auto_create_user',
|
||||||
|
__( 'Automatic XenForo account creation if user don\'t have XF ID', 'romhackplaza' ),
|
||||||
|
function(){
|
||||||
|
global $_romhackplaza;
|
||||||
|
$value = esc_attr( $_romhackplaza->settings->get( 'xf_auto_create_user' ) ?? '0' );
|
||||||
|
|
||||||
|
echo sprintf( '<input type="checkbox" name="%1$s[%2$s]" value="1" %3$s />', 'romhackplaza_plugin_options', 'xf_auto_create_user', checked( $value, '1', false ) );
|
||||||
|
},
|
||||||
|
'romhackplaza-config',
|
||||||
|
'xf',
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---
|
/* ---
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ defined( '\ABSPATH' ) || exit;
|
|||||||
|
|
||||||
class Properties extends Abstract_Extender {
|
class Properties extends Abstract_Extender {
|
||||||
|
|
||||||
public static \WP_Post $current_post;
|
public static \WP_Post|null $current_post;
|
||||||
|
|
||||||
protected function can_extend(): bool
|
protected function can_extend(): bool
|
||||||
{
|
{
|
||||||
@@ -23,7 +23,7 @@ class Properties extends Abstract_Extender {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function change_current_post( \WP_Post $post ): void {
|
public static function change_current_post( \WP_Post|null $post ): void {
|
||||||
|
|
||||||
static::$current_post = $post;
|
static::$current_post = $post;
|
||||||
|
|
||||||
|
|||||||
@@ -111,12 +111,12 @@ class Submissions extends Abstract_Extender {
|
|||||||
'submissions-uploader',
|
'submissions-uploader',
|
||||||
ROMHACKPLAZA_PLUGIN_URI . '/assets/js/submissions/uploader.js',
|
ROMHACKPLAZA_PLUGIN_URI . '/assets/js/submissions/uploader.js',
|
||||||
[],
|
[],
|
||||||
'20251106',
|
'20251106-68',
|
||||||
args: [ 'defer' => true, 'in_footer' => true ]
|
args: [ 'defer' => true, 'in_footer' => true ]
|
||||||
)->enqueue()->add_localize(
|
)->enqueue()->add_localize(
|
||||||
'_romhackplaza_script_uploader',
|
'_romhackplaza_script_uploader',
|
||||||
[ 'submit_url' => admin_url( 'admin-ajax.php' ) ],
|
[ 'submit_url' => admin_url( 'admin-ajax.php' ) ],
|
||||||
);
|
)->enable_i18n();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
233
src/Extenders/XenForo/API.php
Normal file
233
src/Extenders/XenForo/API.php
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RomhackPlaza\Extenders\XenForo;
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
class API {
|
||||||
|
|
||||||
|
const string API_LINK = "api/";
|
||||||
|
|
||||||
|
public static function _build_url( string $endpoint, array $get_args = [] ): string {
|
||||||
|
|
||||||
|
return add_query_arg(
|
||||||
|
$get_args,
|
||||||
|
$_ENV['ROMHACKPLAZA_XF_URL'] . self::API_LINK . $endpoint
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function _do_request(
|
||||||
|
string $action_type,
|
||||||
|
string $url,
|
||||||
|
array $body = [],
|
||||||
|
array $headers = [],
|
||||||
|
bool $need_xf_api_user = false
|
||||||
|
){
|
||||||
|
|
||||||
|
$wp_args = [
|
||||||
|
'headers' => [
|
||||||
|
'XF-Api-Key' => $_ENV['ROMHACKPLAZA_XF_SUPER_USER_API_KEY'],
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
if( $action_type !== 'GET' )
|
||||||
|
$wp_args['body'] = json_encode( $body );
|
||||||
|
|
||||||
|
if( $need_xf_api_user )
|
||||||
|
$wp_args['headers']['XF-Api-User'] = 1;
|
||||||
|
|
||||||
|
$wp_args['headers'] = wp_parse_args( $headers, $wp_args['headers'] );
|
||||||
|
|
||||||
|
$response = null;
|
||||||
|
|
||||||
|
switch ( $action_type ) {
|
||||||
|
case 'GET':
|
||||||
|
$response = wp_remote_get( $url, $wp_args );
|
||||||
|
break;
|
||||||
|
case 'POST':
|
||||||
|
$response = wp_remote_post( $url, $wp_args );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$wp_args['method'] = $action_type;
|
||||||
|
$response = wp_remote_request( $url, $wp_args );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !empty( $response->errors ) ){
|
||||||
|
echo "<script>console.error( `An error occured during a XenForo request.` + `". json_encode( $response->errors ) . "`);</script>";
|
||||||
|
$response = $response->errors;
|
||||||
|
if( is_array( $response ) )
|
||||||
|
$response['api_error'] = true;
|
||||||
|
} else {
|
||||||
|
$response = json_decode( wp_remote_retrieve_body( $response ), ARRAY_A );
|
||||||
|
if( is_array( $response ) )
|
||||||
|
$response['api_error'] = false;
|
||||||
|
}
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function _error_occured( mixed $response ): bool {
|
||||||
|
|
||||||
|
if( is_array( $response ) && isset( $response['api_error'] ) && $response['api_error'] === true )
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* API Methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function post__alerts(
|
||||||
|
int $to_xf_user_id,
|
||||||
|
string $message,
|
||||||
|
string $url = "",
|
||||||
|
string $url_title = "",
|
||||||
|
int $from_xf_user_id = 0,
|
||||||
|
): array|null {
|
||||||
|
|
||||||
|
$url = self::_build_url( 'alerts' );
|
||||||
|
$body = [
|
||||||
|
'to_user_id' => $to_xf_user_id,
|
||||||
|
'alert' => $message,
|
||||||
|
'from_user_id' => $from_xf_user_id,
|
||||||
|
'link_url' => $url,
|
||||||
|
'link_title' => $url_title,
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = self::_do_request( 'POST', $url, $body, need_xf_api_user: true );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function post__auth_login_token(
|
||||||
|
int $xf_user_id,
|
||||||
|
array $body = [],
|
||||||
|
): array|null {
|
||||||
|
|
||||||
|
if( !isset( $body['user_id'] ) )
|
||||||
|
$body['user_id'] = $xf_user_id;
|
||||||
|
|
||||||
|
$url = self::_build_url( 'auth/login-token' );
|
||||||
|
$response = self::_do_request( 'POST', $url, $body );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get__index(
|
||||||
|
|
||||||
|
): array|null {
|
||||||
|
$url = self::_build_url( 'index' );
|
||||||
|
$response = self::_do_request( 'GET', $url );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get__me(
|
||||||
|
): array|null {
|
||||||
|
$url = self::_build_url( "me" );
|
||||||
|
$response = self::_do_request( 'GET', $url );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response['me'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get__users_id(
|
||||||
|
int $xf_user_id,
|
||||||
|
array $body = []
|
||||||
|
){
|
||||||
|
$url = self::_build_url( "users/{$xf_user_id}", $body );
|
||||||
|
$response = self::_do_request( 'GET', $url, need_xf_api_user: true );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function post__users(
|
||||||
|
array $body
|
||||||
|
){
|
||||||
|
$url = self::_build_url( "users" );
|
||||||
|
$response = self::_do_request( 'POST', $url, $body, need_xf_api_user: true );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function post__users_id(
|
||||||
|
int $xf_user_id,
|
||||||
|
array $body
|
||||||
|
){
|
||||||
|
$url = self::_build_url( "users/{$xf_user_id}" );
|
||||||
|
$response = self::_do_request( 'POST', $url, $body, need_xf_api_user: true );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Custom API methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static function get__plaza_alerts_id(
|
||||||
|
int $xf_user_id = 0,
|
||||||
|
): array|null {
|
||||||
|
|
||||||
|
$url = self::_build_url( "plaza-alerts/{$xf_user_id}" );
|
||||||
|
$response = self::_do_request( 'GET', $url, need_xf_api_user: true );
|
||||||
|
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function post__plaza_reports(
|
||||||
|
int $entry_id,
|
||||||
|
string $entry_title,
|
||||||
|
string $entry_url,
|
||||||
|
int $xf_user_id = 0,
|
||||||
|
string $username = "Guest",
|
||||||
|
string $email = "",
|
||||||
|
string $message = "",
|
||||||
|
){
|
||||||
|
|
||||||
|
$url = self::_build_url( "plaza-reports" );
|
||||||
|
|
||||||
|
$body = [
|
||||||
|
'entry_id' => $entry_id,
|
||||||
|
'entry_title' => $entry_title,
|
||||||
|
'entry_url' => $entry_url,
|
||||||
|
'xf_user_id' => $xf_user_id,
|
||||||
|
'username' => $username,
|
||||||
|
'email' => $email,
|
||||||
|
'message' => $message,
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = self::_do_request( 'POST', $url, $body, need_xf_api_user: true );
|
||||||
|
if( self::_error_occured( $response ) )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
13
src/Extenders/XenForo/Abstract_XenForo_Children.php
Normal file
13
src/Extenders/XenForo/Abstract_XenForo_Children.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RomhackPlaza\Extenders\XenForo;
|
||||||
|
use RomhackPlaza\Extenders\Abstract_Extender;
|
||||||
|
|
||||||
|
abstract class Abstract_XenForo_Children extends Abstract_Extender {
|
||||||
|
|
||||||
|
protected function can_extend(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
46
src/Extenders/XenForo/Auth.php
Normal file
46
src/Extenders/XenForo/Auth.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RomhackPlaza\Extenders\XenForo;
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
class Auth extends Abstract_XenForo_Children {
|
||||||
|
|
||||||
|
protected function extend(): void
|
||||||
|
{
|
||||||
|
$this->add_action('wp_login', [ $this, 'auth_on_xenforo' ], 50, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private function verify_xenforo_auth( \WP_User $user, int $xf_user_id ){
|
||||||
|
|
||||||
|
$response = API::get__users_id( $xf_user_id, [ 'with_posts' => false ] );
|
||||||
|
if( $response != null && isset( $response['user']['email'] ) ){
|
||||||
|
return $response['user']['email'] === $user->user_email;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function auth_on_xenforo( string $username, \WP_User $wp_user ) {
|
||||||
|
|
||||||
|
$xf_user_id = absint( get_the_author_meta( XenForo::XF_USER_ID, $wp_user->ID ) ?? 0 );
|
||||||
|
if( $xf_user_id == 0 )
|
||||||
|
return; // Disable login...
|
||||||
|
|
||||||
|
if( !$this->verify_xenforo_auth( $wp_user, $xf_user_id ) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$response = API::post__auth_login_token( $xf_user_id, [
|
||||||
|
'user_id' => $xf_user_id,
|
||||||
|
'return_url' => home_url(),
|
||||||
|
'force' => true,
|
||||||
|
] );
|
||||||
|
|
||||||
|
if( $response != null && isset( $response['login_url'] ) ) {
|
||||||
|
if( wp_redirect( $response['login_url'] ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
174
src/Extenders/XenForo/User_Settings.php
Normal file
174
src/Extenders/XenForo/User_Settings.php
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RomhackPlaza\Extenders\XenForo;
|
||||||
|
use RomhackPlaza\Overrides\Roles;
|
||||||
|
use WP_User;
|
||||||
|
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
class User_Settings extends Abstract_XenForo_Children {
|
||||||
|
|
||||||
|
const array USER_ROLE_SYNC = [
|
||||||
|
Roles::Read_Only->value => 5,
|
||||||
|
Roles::Member->value => 2,
|
||||||
|
Roles::Verified->value => 6,
|
||||||
|
Roles::Moderator->value => 4,
|
||||||
|
Roles::Administrator->value => 3,
|
||||||
|
Roles::Bot->value => 7
|
||||||
|
];
|
||||||
|
|
||||||
|
protected function extend(): void
|
||||||
|
{
|
||||||
|
$this->add_action( 'show_user_profile', [ $this, 'xf_user_id_field'] );
|
||||||
|
$this->add_action( 'edit_user_profile', [ $this, 'xf_user_id_field'] );
|
||||||
|
|
||||||
|
$this->add_action('personal_options_update', [ $this, 'update_xf_user_id_from_profile'] );
|
||||||
|
$this->add_action('edit_user_profile_update', [ $this, 'update_xf_user_id_from_profile'] );
|
||||||
|
|
||||||
|
$this->add_action( 'profile_update', [ $this, 'sync_user_profile' ], 20, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function xf_user_id_field( \WP_User $user ): void {
|
||||||
|
|
||||||
|
global $_romhackplaza;
|
||||||
|
if( !$_romhackplaza->user_roles->current_is_staff() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$field_value = absint( get_the_author_meta( XenForo::XF_USER_ID, $user->ID ) ?? 0 );
|
||||||
|
|
||||||
|
?>
|
||||||
|
<h3 class="heading"><?php _e( "XenForo Config", "romhackplaza" ); ?></h3>
|
||||||
|
<table class="form-table">
|
||||||
|
<tr>
|
||||||
|
<th><label for="<?php echo XenForo::XF_USER_ID; ?>"><?php _e( "XF User ID", "romhackplaza" ); ?></label></th>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="<?php echo XenForo::XF_USER_ID; ?>" id="<?php echo XenForo::XF_USER_ID; ?>" value="<?php echo $field_value != 0 ? strval( $field_value ) : ''; ?>" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update_xf_user_id_from_profile( int $user_id ): void {
|
||||||
|
|
||||||
|
global $_romhackplaza;
|
||||||
|
if( !$_romhackplaza->user_roles->current_is_staff() ) // Can't update this field if not staff member.
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( isset( $_POST[ XenForo::XF_USER_ID ] ) ){
|
||||||
|
|
||||||
|
$field_value = absint( $_POST[ XenForo::XF_USER_ID ] ) ?? 0;
|
||||||
|
if( $field_value != 0 )
|
||||||
|
update_user_meta( $user_id, XenForo::XF_USER_ID, $field_value );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function prepare_sync_user_role( string $role_name, int $user_id ): array{
|
||||||
|
|
||||||
|
global $_romhackplaza;
|
||||||
|
return [
|
||||||
|
'user_group_id' => self::USER_ROLE_SYNC[$role_name],
|
||||||
|
'is_staff' => $_romhackplaza->user_roles->user_is_staff( $user_id )
|
||||||
|
];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sync_user_role( int $user_id ){
|
||||||
|
|
||||||
|
global $_romhackplaza;
|
||||||
|
$role = $_romhackplaza->user_roles->user_upper( $user_id );
|
||||||
|
|
||||||
|
if( $role == null )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$xf_user_id = absint( get_the_author_meta( XenForo::XF_USER_ID, $user_id ) );
|
||||||
|
if( $xf_user_id == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
API::post__users_id( $xf_user_id, self::prepare_sync_user_role( $role->value, $user_id ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create_xenforo_account_from_wp_user( int $user_id ){
|
||||||
|
|
||||||
|
global $_romhackplaza;
|
||||||
|
if( $_romhackplaza->settings->get( 'xf_auto_create_user' ) != '1' )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$wp_user = get_user_by( 'id', $user_id );
|
||||||
|
if( !$wp_user )
|
||||||
|
return;
|
||||||
|
|
||||||
|
$create_user_array = [];
|
||||||
|
$create_user_array['username'] = $wp_user->display_name;
|
||||||
|
|
||||||
|
$role = $_romhackplaza->user_roles->user_upper( $user_id );
|
||||||
|
if( $role != null )
|
||||||
|
$create_user_array = array_merge( $create_user_array, self::prepare_sync_user_role( $role->value, $user_id ) );
|
||||||
|
|
||||||
|
$create_user_array['email'] = sanitize_email( $wp_user->user_email );
|
||||||
|
$create_user_array['password'] = wp_generate_password();
|
||||||
|
$create_user_array['custom_fields']['wp_user_id'] = $user_id;
|
||||||
|
$create_user_array['custom_fields']['wp_entries_number'] = 0;
|
||||||
|
|
||||||
|
$response = API::post__users( $create_user_array );
|
||||||
|
|
||||||
|
if( $response != null && $response['success'] === true && isset( $response['user']['user_id'] ) ){
|
||||||
|
update_user_meta( $user_id, XenForo::XF_USER_ID, $response['user']['user_id'] );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sync_user_profile( int $user_id, \WP_User $old_values ): void {
|
||||||
|
|
||||||
|
$xf_user_id = absint( get_the_author_meta( XenForo::XF_USER_ID, $user_id ) );
|
||||||
|
if( $xf_user_id == 0 ) {
|
||||||
|
$this->create_xenforo_account_from_wp_user($user_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$update_user_array = [];
|
||||||
|
|
||||||
|
// Username change
|
||||||
|
if( !empty( $_POST['display_name'] ) && $_POST['display_name'] !== $old_values->display_name ){
|
||||||
|
$update_user_array['username'] = sanitize_text_field( $_POST['display_name'] );
|
||||||
|
$update_user_array['username_change_visible'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Role change
|
||||||
|
if( !empty( $_POST['role'] ) && !in_array( $_POST['role'], $old_values->roles ) )
|
||||||
|
$update_user_array = array_merge( $update_user_array, self::prepare_sync_user_role( sanitize_text_field( $_POST['role'] ), $user_id ) );
|
||||||
|
|
||||||
|
// E-Mail change
|
||||||
|
if( !empty( $_POST['email'] ) && $_POST['email'] !== $old_values->user_email )
|
||||||
|
$update_user_array['email'] = sanitize_email( $_POST['email'] );
|
||||||
|
|
||||||
|
// Password change
|
||||||
|
if( !empty( $_POST['pass1'] ) && !empty( $_POST['pass2'] ) && $_POST['pass1'] === $_POST['pass2'] )
|
||||||
|
$update_user_array['password'] = esc_attr( $_POST['pass1'] );
|
||||||
|
|
||||||
|
$update_user_array['custom_fields']['wp_user_id'] = $user_id;
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
$response = null;
|
||||||
|
if( $update_user_array != [] )
|
||||||
|
$response = API::post__users_id( $xf_user_id, $update_user_array );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get_number_of_unviewed_alerts( int $user_id ): int {
|
||||||
|
|
||||||
|
$xf_user_id = absint( get_user_meta( $user_id, XenForo::XF_USER_ID, true ) ?? 0 );
|
||||||
|
if( $xf_user_id == 0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
$response = API::get__plaza_alerts_id( $xf_user_id );
|
||||||
|
if( $response != null )
|
||||||
|
return count( $response['alerts'] ?? [] );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
48
src/Extenders/XenForo/XenForo.php
Normal file
48
src/Extenders/XenForo/XenForo.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RomhackPlaza\Extenders\XenForo;
|
||||||
|
use RomhackPlaza\Extenders\Abstract_Extender;
|
||||||
|
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
class XenForo extends Abstract_Extender {
|
||||||
|
|
||||||
|
const string XF_USER_ID = "xf_user_id";
|
||||||
|
|
||||||
|
public User_Settings $users;
|
||||||
|
public Auth $auth;
|
||||||
|
|
||||||
|
public static function api_works(): bool {
|
||||||
|
|
||||||
|
$response = API::get__index();
|
||||||
|
if( $response == null )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( !isset( $response['key']['type'] ) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if( $response['key']['type'] !== 'super' )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable these three settings in .env file to enable XenForo linking.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function can_extend(): bool
|
||||||
|
{
|
||||||
|
return $_ENV['ROMHACKPLAZA_XF_URL'] && $_ENV['ROMHACKPLAZA_XF_SUPER_USER_API_KEY'] && $_ENV['ROMHACKPLAZA_XF_SUPER_USER_ACCOUNT_ID'];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function extend(): void {
|
||||||
|
|
||||||
|
$this->users = new User_Settings();
|
||||||
|
$this->auth = new Auth();
|
||||||
|
|
||||||
|
do_action( "qm/debug", $this->users->get_number_of_unviewed_alerts( 1 ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
46
src/Identifier.php
Normal file
46
src/Identifier.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace RomhackPlaza;
|
||||||
|
defined( 'ABSPATH' ) || exit;
|
||||||
|
|
||||||
|
class Identifier {
|
||||||
|
|
||||||
|
const string CAP_EDIT_POSTS = "edit_posts";
|
||||||
|
const string CAP_EDIT_OTHER_POSTS = "edit_others_posts";
|
||||||
|
|
||||||
|
const string CPT_TRANSLATIONS = "translations";
|
||||||
|
const string CPT_ROMHACKS = "romhacks";
|
||||||
|
const string CPT_HOMEBREWS = "homebrew";
|
||||||
|
const string CPT_UTILITIES = "utilities";
|
||||||
|
const string CPT_DOCUMENTS = "documents";
|
||||||
|
const string CPT_LUA_SCRIPTS = "lua-scripts";
|
||||||
|
const string CPT_TUTORIALS = "tutorials";
|
||||||
|
const string CPT_NEWS = "news";
|
||||||
|
const string CPT_REVIEWS = "reviews";
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const string TAX_GAME = "game";
|
||||||
|
const string TAX_STATUS = "hack-status";
|
||||||
|
const string TAX_LANG = "language";
|
||||||
|
const string TAX_PLATFORM = "platform";
|
||||||
|
const string TAX_AUTHORS = "author-name";
|
||||||
|
const string TAX_UTILITY_CATEGORY = "utility-category";
|
||||||
|
const string TAX_LEVEL = "experience-level";
|
||||||
|
const string TAX_OS = "utility-os";
|
||||||
|
const string TAX_DOCUMENT_CATEGORY = "document-category";
|
||||||
|
const string TAX_MODIFICATIONS = "modifications";
|
||||||
|
const string TAX_HOMEBREW_TYPE = "homebrew-type";
|
||||||
|
const string TAX_NEWS_CATEGORY = "news-category";
|
||||||
|
const string TAX_GENRE = "genre";
|
||||||
|
const string TAX_TUTORIAL_CATEGORY = "tutorial-category";
|
||||||
|
const string TAX_LUA_MODIFICATIONS = "lua-modifications";
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
const string ENTRY_GALLERY = "my_gallery";
|
||||||
|
const string ENTRY_MAIN_IMAGE = "custom_featured_image";
|
||||||
|
|
||||||
|
private function __construct() {}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -91,7 +91,7 @@ class Capabilities extends Abstract_Overrider {
|
|||||||
if( empty( $user_roles ) )
|
if( empty( $user_roles ) )
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return $user_roles |> array_key_first(...)
|
return $user_roles |> array_first(...)
|
||||||
|> Roles::tryFrom(...);
|
|> Roles::tryFrom(...);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ class Plugin {
|
|||||||
$this->children['extend_save_post'] = new Extenders\Post\Save_Post();
|
$this->children['extend_save_post'] = new Extenders\Post\Save_Post();
|
||||||
$this->children['extend_post_properties'] = new Extenders\Post\Properties();
|
$this->children['extend_post_properties'] = new Extenders\Post\Properties();
|
||||||
|
|
||||||
|
$this->children['extend_xenforo'] = new Extenders\XenForo\XenForo();
|
||||||
|
|
||||||
$this->children['extend_acf_pro'] = new Extenders\Advanced_Custom_Fields_Pro();
|
$this->children['extend_acf_pro'] = new Extenders\Advanced_Custom_Fields_Pro();
|
||||||
|
|
||||||
$this->children['override_post_announcements'] = new Overrides\Post_Announcements();
|
$this->children['override_post_announcements'] = new Overrides\Post_Announcements();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class Settings {
|
|||||||
'public_edit_disabled_tag_id' => '',
|
'public_edit_disabled_tag_id' => '',
|
||||||
'discord_webhook_romhacks_translations' => '',
|
'discord_webhook_romhacks_translations' => '',
|
||||||
'discord_webhook_global' => '',
|
'discord_webhook_global' => '',
|
||||||
|
'xf_auto_create_user' => '0',
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->refresh();
|
$this->refresh();
|
||||||
|
|||||||
3
ts/globals.d.ts
vendored
3
ts/globals.d.ts
vendored
@@ -2,5 +2,8 @@
|
|||||||
declare const $: any;
|
declare const $: any;
|
||||||
declare const jQuery: any;
|
declare const jQuery: any;
|
||||||
|
|
||||||
|
/// <reference types="wordpress" />
|
||||||
|
declare const wp: any;
|
||||||
|
|
||||||
/// <reference types="romhackplaza" />
|
/// <reference types="romhackplaza" />
|
||||||
declare function romhackplaza_manage_modal( a: object, b: string|undefined, c: string|undefined, d: string|undefined, e: string|undefined ): void;
|
declare function romhackplaza_manage_modal( a: object, b: string|undefined, c: string|undefined, d: string|undefined, e: string|undefined ): void;
|
||||||
@@ -28,11 +28,11 @@ export class DropContainer {
|
|||||||
|
|
||||||
private addEvents(): void {
|
private addEvents(): void {
|
||||||
|
|
||||||
this.element.addEventListener( 'click', this.submitFile, false );
|
this.element.addEventListener( 'click', (e: Event) => { this.submitFile(e) }, false );
|
||||||
this.element.addEventListener( 'dragover', (e: Event) => e.preventDefault(), false );
|
this.element.addEventListener( 'dragover', (e: Event) => e.preventDefault(), false );
|
||||||
this.element.addEventListener( 'dragenter', (e: Event) => this.element.classList.add( 'drag-active'), false );
|
this.element.addEventListener( 'dragenter', (e: Event) => this.element.classList.add( 'drag-active'), false );
|
||||||
this.element.addEventListener( 'dragleave', (e: Event) => this.element.classList.remove( 'drag-active'), false );
|
this.element.addEventListener( 'dragleave', (e: Event) => this.element.classList.remove( 'drag-active'), false );
|
||||||
this.element.addEventListener( 'drop', this.dropElement );
|
this.element.addEventListener( 'drop', (e: Event) => { this.dropElement( e ); } );
|
||||||
}
|
}
|
||||||
|
|
||||||
submitFile( e: Event ): void {
|
submitFile( e: Event ): void {
|
||||||
|
|||||||
18
ts/submissions/class-reserve-post-id.ts
Normal file
18
ts/submissions/class-reserve-post-id.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import {__, I } from "./globals";
|
||||||
|
declare const _romhackplaza_script_uploader: any;
|
||||||
|
declare const romhackplaza_modal_submissions: any;
|
||||||
|
|
||||||
|
export class Reserve_Post_ID {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param callback - MUST BE FROM A Upload child.
|
||||||
|
*/
|
||||||
|
constructor( callback: () => any ){
|
||||||
|
|
||||||
|
if( I.is_edit ) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import {__, FORBIDDEN_CARS, romhackplaza_modal_submissions, during_upload, I } from "./globals";
|
import {__, FORBIDDEN_CARS, I } from "./globals";
|
||||||
import {DropContainer} from "./class-drop-container";
|
import {DropContainer} from "./class-drop-container";
|
||||||
|
declare const _romhackplaza_script_uploader: any;
|
||||||
|
declare const romhackplaza_modal_submissions: any;
|
||||||
|
|
||||||
export class Upload {
|
export class Upload {
|
||||||
|
|
||||||
file: File;
|
file: File;
|
||||||
|
progress_bar: HTMLElement|undefined;
|
||||||
|
|
||||||
constructor( file: File ){
|
constructor( file: File ){
|
||||||
|
|
||||||
@@ -22,10 +25,20 @@ export class Upload {
|
|||||||
console.error("WTF at beginUpload method.");
|
console.error("WTF at beginUpload method.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.switchDuringUpload();
|
this.switchDuringUpload();
|
||||||
if( typeof I.drop_container !== 'undefined' && I.drop_container instanceof DropContainer )
|
if( typeof I.drop_container !== 'undefined' && I.drop_container instanceof DropContainer )
|
||||||
I.drop_container.switch();
|
I.drop_container.switch();
|
||||||
|
|
||||||
|
let progress = document.getElementById( 'progress' );
|
||||||
|
if( progress !== null ) {
|
||||||
|
progress.style.display = 'block';
|
||||||
|
this.progress_bar = progress.querySelector('.bar') as HTMLElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( I.reserved_post_id === undefined || I.reserved_post_id === null )
|
||||||
|
console.log( "ok" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForbiddenCars() :boolean {
|
checkForbiddenCars() :boolean {
|
||||||
@@ -42,11 +55,20 @@ export class Upload {
|
|||||||
private switchDuringUpload(): void {
|
private switchDuringUpload(): void {
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
during_upload = !during_upload;
|
I.during_upload = !I.during_upload;
|
||||||
|
this.changeStatus( __( "Preparing upload...", 'romhackplaza' ) );
|
||||||
this.switchSubmissionButton();
|
this.switchSubmissionButton();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private changeStatus( str: string ){
|
||||||
|
|
||||||
|
let sts: HTMLElement|null = document.getElementById( 'status' );
|
||||||
|
if( sts !== null )
|
||||||
|
sts.textContent = str;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private switchSubmissionButton(): void {
|
private switchSubmissionButton(): void {
|
||||||
|
|
||||||
let btn: HTMLElement|null = document.getElementById( 'submitTranslationButton' );
|
let btn: HTMLElement|null = document.getElementById( 'submitTranslationButton' );
|
||||||
|
|||||||
52
ts/submissions/class-uploader-data.ts
Normal file
52
ts/submissions/class-uploader-data.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
export class Uploader_Data {
|
||||||
|
|
||||||
|
private data: object;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.data = {};
|
||||||
|
|
||||||
|
return new Proxy( this, {
|
||||||
|
get: ( target, p ) => {
|
||||||
|
return target.get( p as string );
|
||||||
|
},
|
||||||
|
set: ( target, p, v ) => {
|
||||||
|
target.set( p as string, v );
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
add_field( field_name: string, field_value: any, readonly: boolean ){
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if( !this.data[field_name] )
|
||||||
|
// @ts-ignore
|
||||||
|
this.data[field_name] = { "data": field_value, can_write: ( readonly ? 1 : -1 ) };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get( field_name : string ): any {
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if( this.data[field_name] )
|
||||||
|
// @ts-ignore
|
||||||
|
return this.data[field_name]['data'];
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set( field_name: string, field_value: any ){
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if( this.data[field_name] && this.data[field_name]['can_write'] != 0 ){
|
||||||
|
// @ts-ignore
|
||||||
|
this.data[field_name]['data'] = field_value;
|
||||||
|
// @ts-ignore
|
||||||
|
if( this.data[field_name]['can_write'] == 1 )
|
||||||
|
// @ts-ignore
|
||||||
|
this.data[field_name]['can_write'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,17 @@
|
|||||||
export declare const _romhackplaza_script_uploader: any;
|
import {Uploader_Data} from "./class-uploader-data";
|
||||||
export declare const romhackplaza_modal_submissions: any;
|
|
||||||
declare const wp: any;
|
|
||||||
export const { __, _x, _n, _nx } = wp.i18n;
|
|
||||||
|
|
||||||
|
export const { __, _x, _n, _nx } = wp.i18n;
|
||||||
|
|
||||||
export const FORBIDDEN_CARS: Array<string> = [
|
export const FORBIDDEN_CARS: Array<string> = [
|
||||||
"&", "+"
|
"&", "+"
|
||||||
];
|
];
|
||||||
|
|
||||||
export let during_upload = false;
|
export const I : Uploader_Data = new Uploader_Data();
|
||||||
export const I: any = {
|
I.add_field( 'is_edit', false, true );
|
||||||
upload: undefined,
|
I.add_field( 'reserved_post_id', undefined, false );
|
||||||
drop_container: undefined,
|
I.add_field( 'during_upload', false, false );
|
||||||
}
|
I.add_field( 'upload', undefined, false );
|
||||||
|
I.add_field( 'drop_container', undefined, true );
|
||||||
|
|
||||||
export interface Can_Upload_Detail {
|
export interface Can_Upload_Detail {
|
||||||
file: File;
|
file: File;
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
import {type Can_Upload_Detail, during_upload, I} from "./globals";
|
import {type Can_Upload_Detail, I} from "./globals";
|
||||||
import {Upload} from "./class-upload";
|
import {Upload} from "./class-upload";
|
||||||
import {DropContainer} from "./class-drop-container";
|
import {DropContainer} from "./class-drop-container";
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
if( !document.getElementById( 'fileInput' ) ) // Check if exists.
|
if( !document.getElementById( 'file-container' ) ) // Check if exists.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add PostID if edit.
|
||||||
|
let url_params = new URLSearchParams(window.location.search);
|
||||||
|
I.is_edit = url_params.has( 'edit_entry' );
|
||||||
|
I.reserved_post_id = url_params.get('edit_entry' ) || null;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
I.drop_container = new DropContainer( document.getElementById( 'file-container' ) as HTMLElement, document.getElementById( 'file-container-text' ) as HTMLElement );
|
I.drop_container = new DropContainer( document.getElementById( 'file-container' ) as HTMLElement, document.getElementById( 'file-container-text' ) as HTMLElement );
|
||||||
@@ -13,7 +19,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
document.addEventListener( 'can_upload', (e: CustomEvent<Can_Upload_Detail> ) => {
|
document.addEventListener( 'can_upload', (e: CustomEvent<Can_Upload_Detail> ) => {
|
||||||
|
|
||||||
const { file } = e.detail;
|
const { file } = e.detail;
|
||||||
if( !during_upload ) // @ts-ignore
|
if( !I.during_upload ) // @ts-ignore
|
||||||
I.upload = new Upload( file );
|
I.upload = new Upload( file );
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
17
vite-configs/vite.submissions-uploader.config.js
Normal file
17
vite-configs/vite.submissions-uploader.config.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: path.resolve(__dirname, '..'),
|
||||||
|
build: {
|
||||||
|
outDir: 'assets/js/submissions',
|
||||||
|
emptyOutDir: false,
|
||||||
|
|
||||||
|
rollupOptions: {
|
||||||
|
input: 'ts/submissions/index.ts',
|
||||||
|
output: {
|
||||||
|
entryFileNames: `uploader.js`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user