/home/vianto5/hidalgoresidences.mx/wp-content/plugins/code-snippets/php/Client
NameSizeModeActions
Cloud_API.php169920644editdlrm
Cloud_Public_Client.php50340644editdlrm
Welcome_API.php103690644editdlrm
Welcome_Client.php103720644editdlrm
Edit: /home/vianto5/hidalgoresidences.mx/wp-content/plugins/code-snippets/php/Client/Cloud_API.php (16992B)
cloud_url = defined( 'CS_CLOUD_URL' ) ? untrailingslashit( CS_CLOUD_URL ) : 'https://codesnippets.cloud'; $this->cloud_api_url = defined( 'CS_CLOUD_API_URL' ) ? untrailingslashit( CS_CLOUD_API_URL ) : sprintf( '%s/api/v1', $this->cloud_url ); } /** * Retrieve base URL for Code Snippets Cloud. * * @return string */ public function get_cloud_url(): string { return $this->cloud_url; } /** * Retrieve base URL for Code Snippets Cloud API. * * @return string */ public function get_cloud_api_url(): string { return $this->cloud_api_url; } /** * Retrieve the cloud local token. * * @return string */ public function get_local_token(): string { return self::CLOUD_SEARCH_API_TOKEN; } /** * Check if the API key is set and verified. * * @return bool */ public function is_cloud_connection_available(): bool { return false; } /** * Unpack JSON data from a request response. * * @param array|WP_Error $response Response from wp_request_*. * * @return array|null Associative array of JSON data on success, null on failure. */ private function unpack_request_json( $response ): ?array { $body = wp_remote_retrieve_body( $response ); if ( ! $body ) { return null; } $json = json_decode( $body, true ); // Return the whole decoded envelope; each caller extracts the key it needs (search reads // `snippets`/`meta`/`available_filters`, single reads `snippet`, taxonomy reads `data`). return is_array( $json ) ? $json : null; } /** * Create local-to-cloud map to keep track of local snippets that have been synced to the cloud. * * @return Cloud_Link[]|null */ private function get_cloud_links(): ?array { // Return the cached data if available. if ( is_array( $this->cached_cloud_links ) ) { return $this->cached_cloud_links; } // Fetch data from the stored transient, if available. $transient_data = get_transient( self::CLOUD_MAP_TRANSIENT_KEY ); if ( is_array( $transient_data ) ) { $this->cached_cloud_links = $transient_data; return $this->cached_cloud_links; } // Otherwise, regenerate the local-to-cloud-map. $this->cached_cloud_links = []; // Fetch and iterate through all local snippets to create the map. foreach ( get_snippets() as $local_snippet ) { // Skip snippets that are only stored locally. if ( ! $local_snippet->cloud_id ) { continue; } $link = new Cloud_Link(); $cloud_id_owner = $this->get_cloud_id_and_ownership( $local_snippet->cloud_id ); $cloud_id_int = intval( $cloud_id_owner['cloud_id'] ); $link->local_id = $local_snippet->id; $link->cloud_id = $cloud_id_int; $link->is_owner = $cloud_id_owner['is_owner']; // Check if cloud id exists in cloud_id_rev array - this shows if the snippet is in the codevault. $link->in_codevault = $cloud_id_rev[ $cloud_id_int ] ?? false; // Get the cloud snippet revision if in codevault get from cloud_id_rev array otherwise get from cloud. if ( $link->in_codevault ) { $cloud_snippet_revision = $cloud_id_rev[ $cloud_id_int ] ?? $this->get_cloud_snippet_revision( $local_snippet->cloud_id ); $link->update_available = $local_snippet->revision < $cloud_snippet_revision; } $this->cached_cloud_links[] = $link; } set_transient( self::CLOUD_MAP_TRANSIENT_KEY, $this->cached_cloud_links, DAY_IN_SECONDS * self::DAYS_TO_STORE_CS ); return $this->cached_cloud_links; } /** * Get ownership and Cloud ID of a snippet. * * @param string $cloud_id Cloud ID. * * @return array */ public function get_cloud_id_and_ownership( string $cloud_id ): array { $cloud_id_owner = explode( '_', $cloud_id ); return [ 'cloud_id' => (int) $cloud_id_owner[0] ?? '', 'is_owner' => isset( $cloud_id_owner[1] ) && $cloud_id_owner[1], 'is_owner_string' => isset( $cloud_id_owner[1] ) && $cloud_id_owner[1] ? '1' : '0', ]; } /** * Search Code Snippets Cloud. * * @param string $search_method Search by name of codevault or keyword(s). * @param string $search Search query. * @param int $page Search result page to retrieve. Defaults to '1'. * @param int $per_page Number of search results to retrieve per page. * @param array $filters Optional filters: category, type, status. * * @return Cloud_Snippets Result of search query. */ public function fetch_search_results( string $search_method, string $search, int $page = 1, int $per_page = 10, array $filters = [] ): Cloud_Snippets { $per_page = min( self::MAX_RESULTS_PER_PAGE, max( 1, $per_page ) ); $params = [ 's_method' => $search_method, 's' => $search, 'page' => max( 0, $page - 1 ), 'per_page' => $per_page, 'site_token' => self::get_local_token(), 'site_host' => wp_parse_url( get_site_url(), PHP_URL_HOST ), ]; foreach ( [ 'category', 'type', 'status' ] as $key ) { if ( ! empty( $filters[ $key ] ) ) { $params[ $key ] = $filters[ $key ]; } } $api_url = add_query_arg( $params, sprintf( '%s/public/search', $this->get_cloud_api_url() ) ); // The search endpoint can be slow on a cold cache; allow more time than WordPress's // default 5s request timeout so the request is not cut short and returned as empty. $response = wp_remote_get( $api_url, [ 'timeout' => self::SEARCH_REQUEST_TIMEOUT ] ); $json = self::unpack_request_json( $response ); // Pass the full response envelope to Cloud_Snippets, which reads the `data`/`snippets`, // `meta` and `available_filters` keys. Passing only the unpacked `data` list (as before) // dropped the metadata, so the result normalised to an empty set. if ( ! $json ) { return new Cloud_Snippets(); } $results = new Cloud_Snippets( $json ); $results->page = $page; return $results; } /** * Add a new link item to the local-to-cloud map. * * @param Cloud_Link $link Link to add. * * @return void */ public function add_cloud_link( Cloud_Link $link ) { $local_to_cloud_map = get_transient( self::CLOUD_MAP_TRANSIENT_KEY ); $local_to_cloud_map[] = $link; set_transient( self::CLOUD_MAP_TRANSIENT_KEY, $local_to_cloud_map, DAY_IN_SECONDS * self::DAYS_TO_STORE_CS ); } /** * Delete a snippet from local-to-cloud map. * * @param int $snippet_id Local snippet ID. * * @return void */ public function delete_snippet_from_transient_data( int $snippet_id ) { $cloud_links = $this->get_cloud_links(); foreach ( $cloud_links as $link ) { if ( $link->local_id === $snippet_id ) { // Remove the link from the local_to_cloud_map. $index = array_search( $link, $cloud_links, true ); unset( $cloud_links[ $index ] ); } } // Update the transient data. set_transient( self::CLOUD_MAP_TRANSIENT_KEY, $cloud_links, DAY_IN_SECONDS * self::DAYS_TO_STORE_CS ); $this->cached_cloud_links = $cloud_links; } /** * Retrieve a single cloud snippet from the API. * * @param int $cloud_id Remote cloud snippet ID. * * @return Cloud_Snippet Retrieved snippet. */ public function get_single_snippet_from_cloud( int $cloud_id ): Cloud_Snippet { $url = sprintf( '%s/public/getsnippet/%s', $this->get_cloud_api_url(), $cloud_id ); $response = wp_remote_get( $url ); $cloud_snippet = self::unpack_request_json( $response ); return new Cloud_Snippet( is_array( $cloud_snippet ) ? ( $cloud_snippet['snippet'] ?? [] ) : [] ); } /** * Get the current revision of a single cloud snippet. * * @param string $cloud_id Cloud snippet ID. * * @return string|null Revision number on success, null otherwise. */ public function get_cloud_snippet_revision( string $cloud_id ): ?string { $api_url = sprintf( '%s/public/getsnippetrevision/%s', $this->get_cloud_api_url(), $cloud_id ); $cloud_snippet_revision = self::unpack_request_json( wp_remote_get( $api_url ) ); return $cloud_snippet_revision ? $cloud_snippet_revision['snippet_revision'] ?? null : null; } /** * Download a snippet from the cloud. * * @param Cloud_Snippet $snippet_to_store The snippet to be downloaded. * * @return array The result of the download. */ public function download_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): array { $snippet = new Snippet( $snippet_to_store ); // Set the snippet id to 0 to ensure that the snippet is saved as a new snippet. $snippet->id = 0; $snippet->active = 0; $snippet->cloud_id = sprintf( '%d_%d', $snippet_to_store->id, $snippet_to_store->is_owner ? '1' : '0' ); $snippet->desc = $snippet_to_store->description ? $snippet_to_store->description : ''; // Save the snippet to the database. $new_snippet = save_snippet( $snippet ); $link = new Cloud_Link(); $link->local_id = $new_snippet->id; $link->cloud_id = $snippet_to_store->id; $link->is_owner = $snippet_to_store->is_owner; $link->in_codevault = false; $link->update_available = false; $this->add_cloud_link( $link ); return [ 'success' => true, 'action' => 'Single Downloaded', 'snippet_id' => $new_snippet->id, 'link_id' => $link->cloud_id, ]; } /** * Update a snippet from the cloud. * * @param Cloud_Snippet $snippet_to_store Snippet to be updated. * * @return array The result of the update. */ public function update_snippet_from_cloud( Cloud_Snippet $snippet_to_store ): array { $cloud_id = $snippet_to_store->id . '_' . ( $snippet_to_store->is_owner ? '1' : '0' ); $local_snippet = get_snippet_by_cloud_id( sanitize_key( $cloud_id ) ); // Only update the code, active and revision fields. $fields = [ 'code' => $snippet_to_store->code, 'active' => false, 'revision' => $snippet_to_store->revision, ]; update_snippet_fields( $local_snippet->id, $fields ); $this->clear_caches(); return [ 'success' => true, 'action' => __( 'Updated', 'code-snippets' ), ]; } /** * Get the current featured-snippets cache version, initialising it if absent. * * @return string */ private function get_featured_cache_version(): string { $version = get_transient( self::FEATURED_VERSION_OPTION ); if ( ! $version ) { $version = (string) ( microtime( true ) * 1000 ); set_transient( self::FEATURED_VERSION_OPTION, $version, MONTH_IN_SECONDS ); } return $version; } /** * Build the transient key for a specific (version, page, per_page, filters) slot. * * @param int $page Page number (1-indexed). * @param int $per_page Results per page. * @param array $filters Filter values. * * @return string */ private function build_featured_cache_key( int $page, int $per_page, array $filters ): string { $active_filters = array_filter( $filters ); $encoded = wp_json_encode( $active_filters ); $filter_hash = md5( false === $encoded ? '' : $encoded ); $version = $this->get_featured_cache_version(); return self::FEATURED_TRANSIENT_KEY . "_v{$version}_p{$page}_pp{$per_page}_{$filter_hash}"; } /** * Retrieve featured snippets from the cloud API, with transient caching. * * @param int $page Page number (1-indexed). * @param int $per_page Results per page. * @param array $filters Optional filters: category, type, status. * * @return Cloud_Snippets Featured snippets, or an empty result on failure. */ public function get_featured_snippets( int $page = 1, int $per_page = 10, array $filters = [] ): Cloud_Snippets { $per_page = min( self::MAX_RESULTS_PER_PAGE, max( 1, $per_page ) ); $cache_key = self::build_featured_cache_key( $page, $per_page, $filters ); $cached = get_transient( $cache_key ); if ( $cached instanceof Cloud_Snippets ) { return $cached; } $params = [ 'page' => max( 0, $page - 1 ), 'per_page' => $per_page, ]; foreach ( [ 'category', 'type', 'status' ] as $key ) { if ( ! empty( $filters[ $key ] ) ) { $params[ $key ] = $filters[ $key ]; } } $url = add_query_arg( $params, sprintf( '%s/public/featured', $this->get_cloud_api_url() ) ); $response = wp_remote_get( $url, [ 'headers' => [ 'Authorization' => sprintf( 'Bearer %s', self::get_local_token() ), ], ] ); if ( is_wp_error( $response ) ) { return new Cloud_Snippets(); } $json = self::unpack_request_json( $response ); if ( ! $json ) { return new Cloud_Snippets(); } $result = new Cloud_Snippets( $json ); $result->page = $page; set_transient( $cache_key, $result, self::FEATURED_MIN_TTL ); return $result; } /** * Retrieve available snippet types (languages) from the cloud API, with transient caching. * * @return array List of types. */ public function get_cloud_types(): array { $cached = get_transient( self::TYPES_TRANSIENT_KEY ); if ( is_array( $cached ) ) { return $cached; } $response = wp_remote_get( sprintf( '%s/public/types', $this->get_cloud_api_url() ) ); $json = self::unpack_request_json( $response ); if ( ! is_array( $json ) || ! isset( $json['data'] ) ) { return []; } $types = $json['data']; set_transient( self::TYPES_TRANSIENT_KEY, $types, DAY_IN_SECONDS ); return $types; } /** * Retrieve available snippet categories from the cloud API, with transient caching. * * @return array List of categories. */ public function get_cloud_categories(): array { $cached = get_transient( self::CATEGORIES_TRANSIENT_KEY ); if ( is_array( $cached ) ) { return $cached; } $response = wp_remote_get( sprintf( '%s/public/categories', $this->get_cloud_api_url() ) ); if ( is_wp_error( $response ) ) { return []; } $json = self::unpack_request_json( $response ); if ( ! is_array( $json ) || ! isset( $json['data'] ) ) { return []; } $categories = $json['data']; set_transient( self::CATEGORIES_TRANSIENT_KEY, $categories, DAY_IN_SECONDS ); return $categories; } /** * Refresh the cached synced data. * * Bumps the featured-cache version counter so previously cached keys * become unreachable and expire via WordPress's normal transient path. * * @return void */ public function clear_caches() { $this->cached_cloud_links = null; delete_transient( self::CLOUD_MAP_TRANSIENT_KEY ); delete_transient( 'cs_codevault_snippets' ); delete_transient( self::FEATURED_VERSION_OPTION ); } }