ient']); return $data; } /** * Return the storage type * * @return int */ public static function getSType() { return 7; } /** * Returns the storage type icon. * * @return string Returns the storage icon */ public static function getStypeIcon() { $imgUrl = DUPLICATOR_PRO_IMG_URL . '/onedrive.svg'; return '' . esc_attr(static::getStypeName()) . ''; } /** * Returns the storage type name. * * @return string */ public static function getStypeName() { return __('OneDrive', 'duplicator-pro'); } /** * Get storage location string * * @return string */ public function getLocationString() { if (!$this->isAuthorized()) { return __("Not Authenticated", "duplicator-pro"); } else { return $this->config['storage_folder_web_url']; } } /** * Returns an html anchor tag of location * * @return string Returns an html anchor tag with the storage location as a hyperlink. * * @example * OneDrive Example return * https://1drv.ms/f/sAFrQtasdrewasyghg */ public function getHtmlLocationLink() { if ($this->isAuthorized()) { return '' . esc_html($this->getStorageFolder()) . ''; } else { return $this->getLocationString(); } } /** * Check if storage is supported * * @return bool */ public static function isSupported() { return SnapUtil::isCurlEnabled(); } /** * Get supported notice, displayed if storage isn't supported * * @return string html string or empty if storage is supported */ public static function getNotSupportedNotice() { if (static::isSupported()) { return ''; } return esc_html__('OneDrive requires the PHP CURL extension enabled.', 'duplicator-pro'); } /** * Check if storage is valid * * @return bool Return true if storage is valid and ready to use, false otherwise */ public function isValid() { return $this->isAuthorized(); } /** * Is autorized * * @return bool */ public function isAuthorized() { return $this->config['authorized']; } /** * Get the chunk size bytes * * @return int */ public function getUploadChunkSize() { return DynamicGlobalEntity::getInstance()->getVal('onedrive_upload_chunksize_in_kb') * KB_IN_BYTES; } /** * Get the chunk size bytes * * @return int */ public function getDownloadChunkSize() { return DynamicGlobalEntity::getInstance()->getVal('onedrive_download_chunksize_in_kb') * KB_IN_BYTES; } /** * Get upload chunk timeout in seconds * * @return int timeout in microseconds, 0 unlimited */ public function getUploadChunkTimeout() { $global = DUP_PRO_Global_Entity::getInstance(); return (int) ($global->php_max_worker_time_in_sec <= 0 ? 0 : $global->php_max_worker_time_in_sec * SECONDS_IN_MICROSECONDS); } /** * Authorized from HTTP request * * @param string $message Message * * @return bool True if authorized, false if failed */ public function authorizeFromRequest(&$message = '') { try { if (($refreshToken = SnapUtil::sanitizeTextInput(SnapUtil::INPUT_REQUEST, 'auth_code')) === '') { throw new Exception(__('Authorization code is empty', 'duplicator-pro')); } $this->name = SnapUtil::sanitizeTextInput(SnapUtil::INPUT_REQUEST, 'name', ''); $this->notes = SnapUtil::sanitizeDefaultInput(SnapUtil::INPUT_REQUEST, 'notes', ''); $this->config['max_packages'] = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, 'max_packages', 10); $this->config['storage_folder'] = self::getSanitizedInputFolder('storage_folder', 'remove'); $this->revokeAuthorization(); $token = (new TokenEntity(self::getSType(), ['refresh_token' => $refreshToken])); if (! $token->refresh(true)) { throw new Exception(__('Failed to fetch information from OneDrive. Make sure the token is valid.', 'duplicator-pro')); } $this->config['access_token'] = $token->getAccessToken(); $this->config['refresh_token'] = $token->getRefreshToken(); $this->config['token_obtained'] = $token->getCreated(); $this->config['endpoint_url'] = $this->config['resource_id'] = ''; $this->config['authorized'] = true; DUP_PRO_Log::traceObject("OneDrive App folder: ", $storageFolder = $this->getOneDriveStorageFolder()); if (! $storageFolder) { throw new Exception("Failed to fetch information from OneDrive. Make sure the token is valid."); } // Get the storage folder id $this->config['storage_folder_id'] = $storageFolder->id; $this->config['storage_folder_web_url'] = $storageFolder->webUrl; } catch (Exception $e) { DUP_PRO_Log::trace("Problem authorizing OneDrive access token msg: " . $e->getMessage()); $message = $e->getMessage(); return false; } $message = __('OneDrive is connected successfully and Storage Provider Updated.', 'duplicator-pro'); return true; } /** * Revokes authorization * * @param string $message Message * * @return bool True if authorized, false if failed */ public function revokeAuthorization(&$message = '') { if (!$this->isAuthorized()) { $message = __('Onedrive isn\'t authorized.', 'duplicator-pro'); return true; } $this->config['endpoint_url'] = ''; $this->config['resource_id'] = ''; $this->config['access_token'] = ''; $this->config['refresh_token'] = ''; $this->config['token_obtained'] = 0; $this->config['storage_folder_id'] = ''; $this->config['storage_folder_web_url'] = ''; $this->config['authorized'] = false; $message = __('Onedrive is disconnected successfully.', 'duplicator-pro'); return true; } /** * Get external revoke url * * @return string */ public function getExternalRevokeUrl() { $base_url = "https://login.microsoftonline.com/common/oauth2/v2.0/logout"; $fields_arr = [ "client_id" => self::CLIENT_ID, "post_logout_redirect_uri" => self::LOGOUT_REDIRECT_URI, ]; $query = http_build_query($fields_arr); return $base_url . "?$query"; } /** * Get authorization URL * * @return string */ public function getAuthorizationUrl() { return (new TokenService(static::getSType()))->getRedirectUri(); } /** * Returns the config fields template data * * @return array */ protected function getConfigFieldsData() { $hasError = $this->isAuthorized() && !$this->getAdapter()->isValid(); return array_merge($this->getDefaultConfigFieldsData(), [ 'accountInfo' => $this->getAccountInfo(), 'hasError' => $hasError, ]); } /** * Returns the default config fields template data * * @return array */ protected function getDefaultConfigFieldsData() { return [ 'storage' => $this, 'storageFolder' => $this->config['storage_folder'], 'maxPackages' => $this->config['max_packages'], 'allFolderPers' => $this->config['all_folders_perm'], 'accountInfo' => false, 'hasError' => false, 'externalRevokeUrl' => $this->getExternalRevokeUrl(), ]; } /** * Returns the config fields template path * * @return string */ protected function getConfigFieldsTemplatePath() { return 'onedriveaddon/configs/onedrive'; } /** * Update data from http request, this method don't save data, just update object properties * * @param string $message Message * * @return bool True if success and all data is valid, false otherwise */ public function updateFromHttpRequest(&$message = '') { if ((parent::updateFromHttpRequest($message) === false)) { return false; } $this->config['max_packages'] = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, 'onedrive_msgraph_max_files', 10); $oldFolder = $this->config['storage_folder']; $this->config['storage_folder'] = self::getSanitizedInputFolder('_onedrive_msgraph_storage_folder', 'remove'); $this->config['all_folders_perm'] = SnapUtil::sanitizeBoolInput(SnapUtil::INPUT_REQUEST, 'onedrive_msgraph_all_folders_read_write_perm', false); if ($this->isAuthorized() && $oldFolder != $this->config['storage_folder']) { $this->config['storage_folder_id'] = ''; // Create new folder $folder = $this->getOneDriveStorageFolder(); $this->config['storage_folder_id'] = $folder->id; $this->config['storage_folder_web_url'] = $folder->webUrl; $this->save(); } $message = sprintf( __('OneDrive Storage Updated.', 'duplicator-pro'), $this->getStorageFolder() ); return true; } /** * Get account info * * @return false|object */ protected function getAccountInfo() { if (! $this->isAuthorized()) { return false; } $storageFolder = $this->getOneDriveStorageFolder(); if (!$storageFolder || empty($storageFolder->user)) { return false; } return (object) $storageFolder->user; } /** * Get onedrive storage folder * * @return OneDriveStoragePathInfo|false */ protected function getOneDriveStorageFolder() { $adapter = $this->getAdapter(); if (! $adapter->isValid()) { DUP_PRO_Log::trace("OneDrive adapter is not valid, can't get storage folder."); return false; } if (!$this->config['storage_folder_id']) { if (! $adapter->initialize($error)) { DUP_PRO_Log::trace("Failed to initialize OneDrive adapter: $error"); return false; } $folder = $adapter->getPathInfo('/'); $this->config['storage_folder_id'] = $folder->id; $this->save(); } else { $folder = $adapter->getPathInfo('/'); } return $folder; } /** * Get stoage adapter * * @return OnedriveAdapter */ protected function getAdapter() { if (!$this->adapter) { $global = DUP_PRO_Global_Entity::getInstance(); $token = $this->getTokenFromConfig(); $this->adapter = new OneDriveAdapter( $token, $this->config['storage_folder'], $this->config['storage_folder_id'], !$global->ssl_disableverify, ($global->ssl_useservercerts ? '' : DUPLICATOR_PRO_CERT_PATH), DynamicGlobalEntity::getInstance()->getVal('onedrive_http_version', OnedriveAdapter::HTTP_VERSION_AUTO) ); if (! $this->adapter->initialize($error)) { DUP_PRO_Log::trace("Failed to initialize OneDrive adapter: $error"); } } return $this->adapter; } /** * Get the token entity using config values * * @return TokenEntity|false */ public function getTokenFromConfig() { $token = new TokenEntity(self::getSType(), [ 'created' => $this->config['token_obtained'], 'expires_in' => 3600, 'scope' => self::GRAPH_SCOPES, 'access_token' => $this->config['access_token'], 'refresh_token' => $this->config['refresh_token'], ]); if ($token->isAboutToExpire()) { $token->refresh(true); if (!$token->isValid()) { return false; } $this->config['token_obtained'] = $token->getCreated(); $this->config['refresh_token'] = $token->getRefreshToken(); $this->config['access_token'] = $token->getAccessToken(); $this->save(); } return $token; } /** * @return void * @throws Exception */ public static function registerType() { parent::registerType(); add_action('duplicator_update_global_storage_settings', function () { $dGlobal = DynamicGlobalEntity::getInstance(); foreach (static::getDefaultSettings() as $key => $default) { $value = SnapUtil::sanitizeIntInput(SnapUtil::INPUT_REQUEST, $key, $default); $dGlobal->setVal($key, $value); } }); } /** * Get default settings * * @return array */ protected static function getDefaultSettings() { return [ 'onedrive_http_version' => OnedriveAdapter::HTTP_VERSION_AUTO, 'onedrive_upload_chunksize_in_kb' => DUPLICATOR_PRO_ONEDRIVE_UPLOAD_CHUNK_DEFAULT_SIZE_IN_KB, 'onedrive_download_chunksize_in_kb' => self::DEFAULT_DOWNLOAD_CHUNK_SIZE_IN_KB, ]; } /** * @return void */ public static function renderGlobalOptions() { $dGlobal = DynamicGlobalEntity::getInstance(); TplMng::getInstance()->render( 'onedriveaddon/configs/global_options', [ 'uploadChunkSize' => $dGlobal->getVal('onedrive_upload_chunksize_in_kb', DUPLICATOR_PRO_ONEDRIVE_UPLOAD_CHUNK_DEFAULT_SIZE_IN_KB), 'downloadChunkSize' => $dGlobal->getVal('onedrive_download_chunksize_in_kb', self::DEFAULT_DOWNLOAD_CHUNK_SIZE_IN_KB), 'httpVersion' => $dGlobal->getVal('onedrive_http_version', OnedriveAdapter::HTTP_VERSION_AUTO), ] ); } }