{ throw new error_1.TypeORMError(`Function parameter isn't supported in the parameters. Please check "${key}" parameter.`); } if (!key.match(/^([A-Za-z0-9_.]+)$/)) { throw new error_1.TypeORMError("QueryBuilder parameter keys may only contain numbers, letters, underscores, or periods."); } if (this.parentQueryBuilder) { this.parentQueryBuilder.setParameter(key, value); } this.expressionMap.parameters[key] = value; return this; } /** * Adds all parameters from the given object. */ setParameters(parameters) { for (const [key, value] of Object.entries(parameters)) { this.setParameter(key, value); } return this; } createParameter(value) { let parameterName; do { parameterName = `orm_param_${this.parameterIndex++}`; } while (this.hasParameter(parameterName)); this.setParameter(parameterName, value); return `:${parameterName}`; } /** * Adds native parameters from the given object. * * @deprecated Use `setParameters` instead */ setNativeParameters(parameters) { // set parent query builder parameters as well in sub-query mode if (this.parentQueryBuilder) { this.parentQueryBuilder.setNativeParameters(parameters); } Object.keys(parameters).forEach((key) => { this.expressionMap.nativeParameters[key] = parameters[key]; }); return this; } /** * Gets all parameters. */ getParameters() { const parameters = Object.assign({}, this.expressionMap.parameters); // add discriminator column parameter if it exist if (this.expressionMap.mainAlias && this.expressionMap.mainAlias.hasMetadata) { const metadata = this.expressionMap.mainAlias.metadata; if (metadata.discriminatorColumn && metadata.parentEntityMetadata) { const values = metadata.childEntityMetadatas .filter((childMetadata) => childMetadata.discriminatorColumn) .map((childMetadata) => childMetadata.discriminatorValue); values.push(metadata.discriminatorValue); parameters["discriminatorColumnValues"] = values; } } return parameters; } /** * Prints sql to stdout using console.log. */ printSql() { // TODO rename to logSql() const [query, parameters] = this.getQueryAndParameters(); this.connection.logger.logQuery(query, parameters); return this; } /** * Gets generated sql that will be executed. * Parameters in the query are escaped for the currently used driver. */ getSql() { return this.getQueryAndParameters()[0]; } /** * Gets query to be executed with all parameters used in it. */ getQueryAndParameters() { // this execution order is important because getQuery method generates this.expressionMap.nativeParameters values const query = this.getQuery(); const parameters = this.getParameters(); return this.connection.driver.escapeQueryWithParameters(query, parameters, this.expressionMap.nativeParameters); } /** * Executes sql generated by query builder and returns raw database results. */ async execute() { const [sql, parameters] = this.getQueryAndParameters(); const queryRunner = this.obtainQueryRunner(); try { return await queryRunner.query(sql, parameters); // await is needed here because we are using finally } finally { if (queryRunner !== this.queryRunner) { // means we created our own query runner await queryRunner.release(); } } } /** * Creates a completely new query builder. * Uses same query runner as current QueryBuilder. */ createQueryBuilder(queryRunner) { return new thiisabled_btn_html'] = [ 'global_score_widget' => $this->render->get_add_page_btn( 'global-score-widget', $data ), 'rocket_insights' => $this->render->get_add_page_btn( 'rocket-insights', $data ), ]; } wp_send_json_success( $payload ); } /** * Validates a given URL for performance monitoring eligibility. * * @param string $url The URL to validate. * * @return array { * @type bool $error Whether an error occurred during validation. * @type string $message The error message, or an empty string if no error. * @type string $processed_url The URL with protocol added if validation passes. * } */ protected function get_url_validation_payload( string $url ): array { $payload = [ 'error' => false, 'message' => '', 'processed_url' => '', ]; if ( 'local' === wp_get_environment_type() ) { $payload['error'] = true; $payload['message'] = 'Performance monitoring is disabled for local environment'; return $payload; } // Validate that performance monitoring is not disabled. if ( ! $this->context->is_allowed() ) { $payload['error'] = true; $payload['message'] = 'Performance monitoring is disabled.'; return $payload; } // Validate that url is not empty. if ( '' === $url ) { $payload['error'] = true; $payload['message'] = 'No url provided.'; return $payload; } // Check if URL has protocol, add if needed. $url = rocket_add_url_protocol( $url ); $payload['processed_url'] = $url; $response = $this->get_page_content( $url ); if ( ! $response ) { $payload['error'] = true; $payload['message'] = 'Url does not resolve to a valid page.'; return $payload; } // check if url is not from admin. if ( strpos( $url, admin_url() ) === 0 ) { $payload['error'] = true; $payload['message'] = 'Url is an admin page.'; return $payload; } // Check if url has not been submited. if ( false !== $this->manager->get_single_job( $url, true ) ) { $payload['error'] = true; $payload['message'] = 'Page url performance is already been monitored.'; return $payload; } // Fetch url body and send to payload. $payload['message'] = $response; return $payload; } /** * Handles AJAX request to retrieve performance monitoring results for given IDs. * * @return void Outputs JSON response and terminates execution. */ public function get_results(): void { check_ajax_referer( 'rocket-ajax', 'nonce', true ); $payload = []; // Check if ids is set. if ( empty( $_GET['ids'] ) || ! is_array( $_GET['ids'] ) ) { $payload['results'] = 'No ids param available or ids not array'; wp_send_json_error( $payload ); } // Ensure everything is treated as integer. $ids = array_map( 'intval', $_GET['ids'] ); // Remove anything that is not a valid integer > 0. $ids = array_filter( $ids ); // Keep index clean. $ids = array_values( $ids ); if ( empty( $ids ) ) { $payload['results'] = 'ids empty'; wp_send_json_error( $payload ); } $query_params = [ 'id__in' => $ids, ]; $results = $this->query->query( $query_params ); // Result is empty. if ( empty( $results ) ) { $payload['results'] = 'No rows found in DB for ids: ' . implode( ',', $ids ); wp_send_json_error( $payload ); } foreach ( $results as $result ) { $result->html = $this->render->get_performance_monitoring_list_row( $result ); } $payload['results'] = $results; $payload['global_score_data'] = $this->get_global_score_payload(); $payload['has_credit'] = $this->plan->has_credit(); $payload['can_add_pages'] = $this->context->is_adding_page_allowed(); wp_send_json_success( $payload ); } /** * Reset testing a page using its ID. * * @return void */ public function reset_page() { check_ajax_referer( 'rocket-ajax', 'nonce', true ); $id = ! empty( $_POST['id'] ) ? intval( $_POST['id'] ) : 0; if ( empty( $id ) ) { wp_send_json_error( [ 'error' => true, 'message' => __( 'No ID was provided.', 'rocket' ), ] ); } $row = $this->query->get_row_by_id( $id ); if ( ! $row ) { wp_send_json_error( [ 'error' => true, 'message' => __( 'Not valid ID', 'rocket' ), ] ); } $this->manager->add_to_the_queue( $row->url, // @phpstan-ignore-line true, [ 'data' => [ 'is_retest' => true, ], 'score' => '', 'report_url' => '', 'is_blurred' => 0, ] ); /** * Fires when a performance monitoring job is reset/retested. * * @since 3.20 * * @param int $id The database row ID of the reset job. */ do_action( 'rocket_pm_job_retest', $id ); $row = $this->query->get_row_by_id( $id ); wp_send_json_success( [ 'id' => $id, 'html' => $this->render->get_performance_monitoring_list_row( $row ), 'global_score_data' => $this->get_global_score_payload(), 'remaining_urls' => $this->get_remaining_url_count(), 'has_credit' => $this->plan->has_credit(), 'can_add_pages' => $this->context->is_adding_page_allowed(), ] ); } /** * Retrieves the global performance score payload for AJAX responses. * * Gets the global score data, determines the status color, and generates the HTML * for the global score widget. * * @return array { * @type array $data Global score data including score, pages_num, status, and status-color. * @type string $html Rendered HTML for the global score widget. * } */ private function get_global_score_payload() { $payload = $this->global_score->get_global_score_data(); $payload['status-color'] = $this->render->get_score_color_status( (int) $payload['score'] ); $payload['remaining_urls'] = $this->get_remaining_url_count(); return [ 'data' => $payload, 'html' => $this->render->get_global_score_widget_content( $payload ), 'row_html' => $this->render->get_global_score_row( $payload ), ]; } /** * Get the remaining number of URLs that can be added based on user's plan limit. * * @return int Number of URLs that can still be added. */ private function get_remaining_url_count(): int { return max( 0, $this->plan->max_urls() - (int) $this->query-> get_total_count() ); } }