function _xfac_api_curl($url, $method = 'GET', $postFields = null, $curlOptions = array(), $xfacOptions = array()) { $ch = curl_init(); $requestHeaders = array(); $GLOBALS['_xfac_api_curlHeaders'] = array(); $serverIp = get_option('xfac_server_ip'); if (!empty($serverIp)) { // we need to connect directly to this address $urlHost = parse_url($url, PHP_URL_HOST); if (!empty($urlHost)) { $urlHostPos = strpos($url, $urlHost); if ($urlHostPos !== false) { $url = substr_replace($url, $serverIp, $urlHostPos, strlen($urlHost)); $requestHeaders['Host'] = 'Host: ' . $urlHost; } } } curl_setopt($ch, CURLOPT_URL, $url); switch ($method) { case 'GET': // default is GET break; case 'POST': curl_setopt($ch, CURLOPT_POST, true); break; default: curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); break; } curl_setopt($ch, CURLOPT_HTTPHEADER, array_values($requestHeaders)); if (is_array($postFields)) { curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postFields)); } elseif (is_string($postFields)) { curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields); } curl_setopt($ch, CURLOPT_HEADERFUNCTION, "_xfac_api_curlHeaderFunction"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); foreach ($curlOptions as $option => $value) { curl_setopt($ch, $option, $value); } $body = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $result = array('http_code' => $httpCode, 'headers' => $GLOBALS['_xfac_api_curlHeaders'], 'body' => $body); $headerContentType = _xfac_api_getHeader($result, 'Content-Type'); if (strpos(implode('', $headerContentType), 'json') !== false) { $result['parts'] = json_decode($body, true); } else { $result['parts'] = array(); } if ($httpCode < 200 || $httpCode > 299 || empty($result['parts']) || !empty($result['parts']['error'])) { xfac_log('_xfac_api_curl %s (%s, %s) -> %s', $method, $url, var_export($postFields, true), $httpCode); foreach ($result['headers'] as $headerLine) { xfac_log(' | %s', $headerLine); } xfac_log(' | %s', $body); } return $result; }
function xfac_syncComment_pullComment($config, $xfPost, $wpPostId, $direction = 'pull') { $wpUserUrl = ''; $wpUserId = 0; $wpUserData = xfac_user_getUserDataByApiData($config['root'], $xfPost['poster_user_id']); if (empty($wpUserData)) { if (intval(get_option('xfac_sync_comment_xf_wp_as_guest')) == 0) { return 0; } // no wordpress user found but as_guest option is enabled // sync as guest now $wpDisplayName = $xfPost['poster_username']; $wpUserEmail = sprintf('*****@*****.**', $xfPost['poster_username'], $xfPost['poster_user_id']); } else { $wpDisplayName = $wpUserData->display_name; $wpUserEmail = $wpUserData->user_email; $wpUserUrl = $wpUserData->user_url; $wpUserId = $wpUserData->ID; } $commentDateGmt = gmdate('Y-m-d H:i:s', $xfPost['post_create_date']); $commentDate = get_date_from_gmt($commentDateGmt); $commentContent = xfac_api_filterHtmlFromXenForo($xfPost['post_body_html']); $comment = array('comment_post_ID' => $wpPostId, 'comment_author' => $wpDisplayName, 'comment_author_email' => $wpUserEmail, 'comment_author_url' => $wpUserUrl, 'comment_content' => $commentContent, 'user_id' => $wpUserId, 'comment_date_gmt' => $commentDateGmt, 'comment_date' => $commentDate, 'comment_approved' => 1); $XFAC_SKIP_xfac_save_comment_before = !empty($GLOBALS['XFAC_SKIP_xfac_save_comment']); $GLOBALS['XFAC_SKIP_xfac_save_comment'] = true; $commentId = wp_insert_comment($comment); $GLOBALS['XFAC_SKIP_xfac_save_comment'] = $XFAC_SKIP_xfac_save_comment_before; if ($commentId > 0) { xfac_sync_updateRecord('', 'post', $xfPost['post_id'], $commentId, 0, array('post' => $xfPost, 'direction' => $direction)); xfac_log('xfac_syncComment_pullComment pulled $xfPost (#%d) -> $wpComment (#%d)', $xfPost['post_id'], $commentId); } else { xfac_log('xfac_syncComment_pullComment failed pulling $xfPost (#%d)', $xfPost['post_id']); } return $commentId; }
function xfac_option_getMeta($config) { static $rebuiltCount = 0; if (empty($config)) { return array(); } $meta = get_option('xfac_meta'); $rebuild = false; if (empty($meta) or empty($meta['linkIndex'])) { $rebuild = true; } else { foreach ($config as $configKey => $configValue) { if (empty($meta[$configKey]) or $meta[$configKey] !== $configValue) { $rebuild = true; break; } } } $xfAdminAccountOption = intval(get_option('xfac_xf_admin_account')); $xfAdminAccountMeta = empty($meta['xfac_xf_admin_account']) ? 0 : intval($meta['xfac_xf_admin_account']); if ($xfAdminAccountMeta !== $xfAdminAccountOption) { $rebuild = true; } if ($rebuild and !empty($_REQUEST['oauth_token'])) { // looks like admin enter WordPress url as the root, abort rebuilding $rebuild = false; } if ($rebuild and $rebuiltCount > 0) { // we rebuild once, only retry if $meta is empty if (!empty($meta)) { $rebuild = false; } } if ($rebuild) { xfac_updateNotice('xf_guest_account'); xfac_updateNotice('xf_admin_account'); $meta = $config; $meta['linkIndex'] = xfac_api_getPublicLink($config, 'index'); $meta['modules'] = array(); $meta['forums'] = array(); if (!empty($meta['linkIndex'])) { if ($xfAdminAccountOption) { $adminAccessToken = xfac_user_getAdminAccessToken($config); if (empty($adminAccessToken)) { // unable to obtain admin access token // probably a missing record or expired refresh token // reset the option update_option('xfac_xf_admin_account', 0); $xfAdminAccountOption = 0; } } $xfGuestAccountOption = intval(get_option('xfac_xf_guest_account')); if ($xfGuestAccountOption) { $guestAccessToken = xfac_user_getSystemAccessToken($config); if (empty($guestAccessToken)) { // unable to obtain guest access token // probably an expired refresh token // reset the option update_option('xfac_xf_guest_account', 0); } else { $mappedTags = xfac_syncPost_getMappedTags(); if (!empty($mappedTags)) { // make sures the guest account follows required forums // and have the needed notification subscription xfac_syncPost_followForums($config, $guestAccessToken, array_keys($mappedTags)); } } } $meta['modules'] = xfac_api_getModules($config); $meta['linkAlerts'] = xfac_api_getPublicLink($config, 'account/alerts'); $meta['linkConversations'] = xfac_api_getPublicLink($config, 'conversations'); $meta['linkLogin'] = xfac_api_getPublicLink($config, 'login'); $meta['linkLoginLogin'] = xfac_api_getPublicLink($config, 'login/login'); $meta['linkRegister'] = xfac_api_getPublicLink($config, 'register'); $forums = xfac_api_getForums($config); if (!empty($forums['forums'])) { $meta['forums'] = $forums['forums']; } $meta['xfac_xf_admin_account'] = $xfAdminAccountOption; if (!empty($meta['xfac_xf_admin_account'])) { $userGroups = xfac_api_getUserGroups($config, 0, xfac_user_getAdminAccessToken($config)); if (!empty($userGroups['user_groups'])) { $meta['userGroups'] = $userGroups['user_groups']; } } } $rebuiltCount++; update_option('xfac_meta', $meta); xfac_log('xfac_option_getMeta rebuilt $meta=%s', $meta); } return $meta; }
function xfac_profile_update_user_pass($wpUserId) { if (empty($GLOBALS['_xfac_syncLogin_pending_user_pass'])) { // no data return; } $pending = $GLOBALS['_xfac_syncLogin_pending_user_pass']; if (!is_array($pending) || count($pending) != 2) { // data unrecognized return; } if ($pending[0] != $wpUserId) { // user_id not matched return; } $config = xfac_option_getConfig(); if (empty($config)) { // no config return; } $adminAccessToken = xfac_user_getAdminAccessToken($config); if (empty($adminAccessToken)) { // no admin access token return; } $records = xfac_user_getRecordsByUserId($wpUserId); if (empty($records)) { // no user record return null; } $record = reset($records); xfac_api_postUserPassword($config, $adminAccessToken, $record->identifier, $pending[1]); xfac_log('xfac_profile_update_user_pass pushed password for $wpUser (#%d)', $wpUserId); }
function xfac_tools_connect() { /** @var wpdb $wpdb */ global $wpdb; $config = xfac_option_getConfig(); if (empty($config)) { wp_die(__('XenForo API configuration is missing.', 'xenforo-api-consumer')); } $adminAccessToken = xfac_user_getAdminAccessToken($config); if (empty($adminAccessToken)) { wp_die(__('Admin Account\'s access token cannot be obtained.', 'xenforo-api-consumer')); } if (!xfac_api_hasModuleVersion($config, 'forum', 2015030901) || !xfac_api_hasModuleVersion($config, 'oauth2', 2015030902)) { wp_die(__('Please update XenForo API to run this tool.', 'xenforo-api-consumer')); } $optionFilters = array('position' => array('filter' => FILTER_VALIDATE_INT, 'default' => 0), 'limit' => array('filter' => FILTER_VALIDATE_INT, 'default' => 10), 'associate' => array('filter' => FILTER_VALIDATE_INT, 'default' => 0), 'push' => array('filter' => FILTER_VALIDATE_INT, 'default' => 0)); $options = array(); foreach ($optionFilters as $optionKey => $optionFilter) { $optionValue = filter_input(INPUT_GET, $optionKey, $optionFilter['filter']); if (!empty($optionValue)) { $options[$optionKey] = $optionValue; } else { $options[$optionKey] = $optionFilter['default']; } } if (empty($options['associate']) && empty($options['push'])) { wp_die(__('At least one action must be selected: either associate or push', 'xenforo-api-consumer')); } $maxWpUserIds = $wpdb->get_var('SELECT MAX(ID) FROM ' . $wpdb->prefix . 'users'); if ($options['position'] >= $maxWpUserIds) { die(__('Done.', 'xenforo-api-consumer')); } $dbUsers = $wpdb->get_results(' SELECT * FROM ' . $wpdb->prefix . 'users WHERE ID > ' . $options['position'] . ' LIMIT ' . $options['limit']); foreach ($dbUsers as $dbUser) { $user = new WP_User($dbUser); $options['position'] = max($options['position'], $user->ID); $records = xfac_user_getRecordsByUserId($user->ID); if (!empty($records)) { // this user has connected continue; } printf(__('Processing user #%d (%s)', 'xenforo-api-consumer'), $user->ID, $user->user_login); echo "<br />\n"; $candidates = array(); $userLoginUsers = xfac_api_getUsersFind($config, $user->user_login); if (!empty($userLoginUsers['users'])) { foreach ($userLoginUsers['users'] as $userLoginUser) { // similar logic with includes/dashboard/profile.php if (strlen($userLoginUser['username']) == strlen($user->user_login)) { $candidates[$userLoginUser['user_id']] = $userLoginUser; } } } $emailUsers = xfac_api_getUsersFind($config, '', $user->user_email, $adminAccessToken); if (!empty($emailUsers['users'])) { foreach ($emailUsers['users'] as $emailUser) { $candidates[$emailUser['user_id']] = $emailUser; } } if (!empty($candidates) && !empty($options['associate'])) { foreach ($candidates as $candidate) { $userAccessToken = xfac_api_postOauthTokenAdmin($config, $adminAccessToken, $candidate['user_id']); if (!empty($userAccessToken)) { xfac_syncLogin_syncRole($config, $user, $candidate, false); xfac_user_updateRecord($user->ID, $config['root'], $candidate['user_id'], $candidate, $userAccessToken); xfac_log('xfac_tools_connect associated $wpUser (#%d) vs. $xfUser (#%d)', $user->ID, $candidate['user_id']); } else { $errors = xfac_api_getLastErrors(); if (!is_array($errors)) { $errors = array(__('Unknown error', 'xenforo-api-consumer')); } xfac_log('xfac_tools_connect failed to associate $wpUser (#%d) vs. $xfUser (#%d): %s', $user->ID, $candidate['user_id'], implode(', ', $errors)); } } } if (empty($candidates) && !empty($options['push'])) { $result = xfac_api_postUser($config, $user->user_email, $user->user_login, '', array('oauth_token' => $adminAccessToken)); if (!empty($result)) { $xfUser = $result['user']; $token = $result['token']; xfac_syncLogin_syncRole($config, $user, $xfUser, false); xfac_user_updateRecord($user->ID, $config['root'], $xfUser['user_id'], $xfUser, $token); xfac_log('xfac_tools_connect pushed $wpUser (#%d)', $user->ID); } else { $errors = xfac_api_getLastErrors(); if (!is_array($errors)) { $errors = array(__('Unknown error', 'xenforo-api-consumer')); } xfac_log('xfac_tools_connect failed to push $wpUser (#%d): %s', $user->ID, implode(', ', $errors)); } } } $optionsStr = ''; foreach ($options as $optionKey => $optionValue) { if ($optionValue !== $optionFilters[$optionKey]['default']) { $optionsStr .= sprintf('&%s=%s', $optionKey, rawurlencode($optionValue)); } } die(sprintf('<script>window.location = "%s";</script>', admin_url(sprintf('tools.php?action=xfac_tools_connect%s', $optionsStr)))); }
function xfac_syncPost_pullPost($config, $thread, $tags, $direction = 'pull') { if (empty($thread['creator_user_id'])) { return 0; } $wpUserData = xfac_user_getUserDataByApiData($config['root'], $thread['creator_user_id']); if (empty($wpUserData)) { return 0; } $postAuthor = $wpUserData->ID; $wpUser = new WP_User($wpUserData); $postTypeObj = get_post_type_object('post'); if (empty($postTypeObj)) { // no post type object?! return 0; } if (!$wpUser->has_cap($postTypeObj->cap->create_posts)) { // no permission to create posts xfac_log('xfac_syncPost_pullPost skipped pulling post because of lack of create_posts capability (user #%d)', $wpUser->ID); return 0; } $postDateGmt = gmdate('Y-m-d H:i:s', $thread['thread_create_date']); $postDate = get_date_from_gmt($postDateGmt); $postStatus = 'draft'; if (intval(get_option('xfac_sync_post_xf_wp_publish')) > 0) { $postStatus = 'publish'; } $postContent = xfac_api_filterHtmlFromXenForo($thread['first_post']['post_body_html']); $wpPost = array('post_author' => $postAuthor, 'post_content' => $postContent, 'post_date' => $postDate, 'post_date_gmt' => $postDateGmt, 'post_status' => $postStatus, 'post_title' => $thread['thread_title'], 'post_type' => 'post', 'tags_input' => implode(', ', $tags)); $XFAC_SKIP_xfac_save_post_before = !empty($GLOBALS['XFAC_SKIP_xfac_save_post']); $GLOBALS['XFAC_SKIP_xfac_save_post'] = true; $wpPostId = wp_insert_post($wpPost); $GLOBALS['XFAC_SKIP_xfac_save_post'] = $XFAC_SKIP_xfac_save_post_before; if ($wpPostId > 0) { $subscribed = array(); if (intval(get_option('xfac_sync_comment_xf_wp')) > 0) { $accessToken = xfac_user_getAccessToken($wpUser->ID); if (!empty($accessToken)) { $xfPosts = xfac_api_getPostsInThread($config, $thread['thread_id'], $accessToken); if (empty($xfPosts['subscription_callback']) and !empty($xfPosts['_headerLinkHub'])) { if (xfac_api_postSubscription($config, $accessToken, $xfPosts['_headerLinkHub'])) { $subscribed = array('hub' => $xfPosts['_headerLinkHub'], 'time' => time()); } } } } xfac_sync_updateRecord('', 'thread', $thread['thread_id'], $wpPostId, $thread['thread_create_date'], array('forumId' => $thread['forum_id'], 'thread' => $thread, 'direction' => $direction, 'sticky' => !empty($thread['thread_is_sticky']), 'subscribed' => $subscribed)); xfac_log('xfac_syncPost_pullPost pulled $xfThread (#%d) as $wpPost (#%d)', $thread['thread_id'], $wpPostId); } else { xfac_log('xfac_syncPost_pullPost failed pulling $xfThread (#%d)'); } return $wpPostId; }
function xfac_subscription_handleCallback(array $json) { $config = xfac_option_getConfig(); if (empty($config['clientId'])) { return; } $xfThreadIds = array(); $xfPostIds = array(); // phrase 1: preparation foreach ($json as &$pingRef) { if (empty($pingRef['client_id']) or $pingRef['client_id'] != $config['clientId']) { continue; } if (empty($pingRef['topic'])) { continue; } $parts = explode('_', $pingRef['topic']); $pingRef['topic_id'] = array_pop($parts); $pingRef['topic_type'] = implode('_', $parts); switch ($pingRef['topic_type']) { case 'thread_post': $xfThreadIds[] = $pingRef['topic_id']; $xfPostIds[] = $pingRef['object_data']; break; } } // phrase 2: fetch sync records $postSyncRecords = array(); if (!empty($xfPostIds)) { $postSyncRecords = xfac_sync_getRecordsByProviderTypeAndIds('', 'thread', $xfThreadIds); } $commentSyncRecords = array(); if (!empty($xfPostIds)) { $commentSyncRecords = xfac_sync_getRecordsByProviderTypeAndIds('', 'post', $xfPostIds); } // phrase 3: sync data foreach ($json as &$pingRef) { if (empty($pingRef['topic_type'])) { continue; } switch ($pingRef['topic_type']) { case 'thread_post': $postSyncRecord = null; $commentSyncRecord = null; foreach ($postSyncRecords as $_postSyncRecord) { if ($_postSyncRecord->provider_content_id == $pingRef['topic_id']) { $postSyncRecord = $_postSyncRecord; } } if (!empty($postSyncRecord)) { foreach ($commentSyncRecords as $_commentSyncRecord) { if ($_commentSyncRecord->provider_content_id == $pingRef['object_data']) { $commentSyncRecord = $_commentSyncRecord; } } $pingRef['result'] = _xfac_subscription_handleCallback_threadPost($config, $pingRef, $postSyncRecord, $commentSyncRecord); if (!empty($pingRef['result'])) { xfac_sync_updateRecordDate($postSyncRecord); if (!empty($commentSyncRecord)) { xfac_sync_updateRecordDate($commentSyncRecord); } } } break; case 'user_notification': $pingRef['result'] = _xfac_subscription_handleCallback_userNotification($config, $pingRef); break; case 'user': $pingRef['result'] = _xfac_subscription_handleCallback_user($config, $pingRef); break; } } // phrase 4: output results $results = array(); foreach ($json as $ping) { if (!empty($ping['result'])) { $results[] = $ping; xfac_log('xfac_subscription_handleCallback %s/%s -> %s', $ping['topic_type'], $ping['topic_id'], $ping['result']); } } echo json_encode($results); }