mirror of
https://gh.wpcy.net/https://github.com/elementor/one-click-accessibility.git
synced 2026-04-21 11:32:30 +08:00
* PHPCS and remediation POC WIP * WIP Wizard module * Added scanner module * [APP-929][APP-930] Add initial setup for wizard, added btn to the topbar (#230) * [APP-929][APP-930] * [APP-929][APP-930] * update logic * update init app * [APP-0000] store plan scope after register/switch * change return of load * add header * Move into shadow dom, add context, add headers components * add UI components * add UI components * add UI components * merge current develop * merge current develop * Add AltText Form * Add scroll to current element * Align with current design, add loader, added preview for svg * Align with current design, add loader, added preview for svg * Resolve comments * Resolve comments * Resolve comments * [APP-934] add submit logic (#259) * [APP-934] add submit logic * [APP-934] add submit logic * [APP-934] add submit logic * [APP-934] add submit logic * Added replace remediation action * Add submit logic * Add submit alt text logic, generate AI alt text * Add AI generate request, add convert from SVG to png base64, added manual fix block * Add AI generate request, add convert from SVG to png base64, added manual fix block * Add texts, add remediation submit, fix logic to store remediation * Add texts, add remediation submit, fix logic to store remediation * Add texts, add remediation submit, fix logic to store remediation * Add texts, add remediation submit, fix logic to store remediation * Add texts, add remediation submit, fix logic to store remediation * Add texts, add remediation submit, fix logic to store remediation --------- Co-authored-by: Raz Ohad <admin@bainternet.info> * Add texts, add remediation submit, fix logic to store remediation * [APP-0000] add store request to the Service API (#268) * [APP-0000] add store request to the Service API * [APP-0000] add store request to the Service API * [APP-0000] add store request to the Service API * [APP-0000] add store request to the Service API * [APP-0000] add request to store scanner summary * [APP-0000] add request to store scanner summary * [APP-0000] add request to store scanner summary * [APP-1432] fix with AI flow (#275) * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1432] fix with AI flow * [APP-1446] sidebar menu update (#276) * update: simplify menu * add: headings and scanner menu options * [APP-945] add column for tables (#282) * [APP-945] add column for tables * [APP-945] add column for tables * [APP-945] add column for tables * [APP-945] add column for tables * [APP-1447] Updated quota bar designs (#278) * update: quota bar designs * fix: the popover was partially visible * update: AI credits name * update: usage calculation logic * add: quota indicators * update: quotas tooltip text * update: quotas notices text * update: make toggle icon dynamic * fix: @elementor/ui imports * Update modules/settings/assets/js/layouts/quota-bar.js Co-authored-by: VasylD <vasyld@elementor.red> * update: styling of component --------- Co-authored-by: VasylD <vasyld@elementor.red> * [APP-1507] add UI changes (#286) * [APP-1507] add UI changes * [APP-1507] add UI changes * [APP-1507] add UI changes * [APP-1507] add UI changes * [APP-1507] add UI changes * [APP-1507] add UI changes * [APP-1507] add UI changes * [APP-1387] add mixpanel events (#288) * [APP-1387] add mixpanel events * [APP-1387] add mixpanel events * New: Add the a11y assistant dashboard's UI [APP-1445] (#289) * [APP-1513] add disconnected msg (#290) * [APP-1513] add disconnected msg * [APP-1513] add disconnected msg * [APP-1513] add disconnected msg * [APP-1547][APP-1548][APP-948] update alt text view, fix list issues (#291) * [APP-1547][APP-1548][APP-948] update alt text view, fix list issues, add rest route for update status * [APP-1547][APP-1548][APP-948] update alt text view, fix list issues, add rest route for update status * fix: infotip icon padding and font style (#293) * fix: infotip icon padding and font style * fix: infotip icon padding and font style * update: caniuse database * [APP-1525] add edit mode (#294) * [APP-1525] add edit mode * [APP-1525] add edit mode * [APP-1525] add edit mode * Bug/app 1544 (#295) * Fix: Resolve QA comments [APP-1544] * New: Add beta tags [APP-1555] * New: Add the "no results" state [APP-1544] * [APP-1554] rename violations (#297) * [APP-1512] add backend logic for remediation management (#298) * [APP-1512] add backend logic for remediation management * [APP-1512] add backend logic for remediation management * Update modules/remediation/database/remediation-entry.php Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * Update modules/remediation/rest/items.php Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * [APP-1512] add backend logic for remediation management --------- Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * Fix: Resolve QA comments [n/a] (#299) * [APP-1512] add FE remediation management (#300) * [APP-1512] add backend logic for remediation management * [APP-1512] add backend logic for remediation management * Update modules/remediation/database/remediation-entry.php Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * Update modules/remediation/rest/items.php Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * [APP-1512] add backend logic for remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management * [APP-1512] add FE remediation management --------- Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * [APP-1609] fix tooltip * [APP-1609] fix resolved btn click * [APP-1401] clear cache on update (#302) * [APP-1401] clear cache on update * [APP-1401] clear cache on update * [APP-1401] clear cache on update * [APP-1401] clear cache on update * [APP-1401] clear cache on update * update with latest develop branch * fix copies * [APP-1619] add mixpanel event (#303) * [APP-1619] add mixpanel event * [APP-1619] add mixpanel event * [APP-1593] Add locked variant for quota bar (#301) * update: add locked version of quota status bar * fix: text color for infotip * fix: width issues * fix: add check for 0 * [APP-1637][APP-1643] add UI fixes, add excluded rules array (#307) * fix: make sidebar collapsible (#306) * Merge current dev * [APP-1603] Add dashboard menu (#309) * [APP-1603] Add dashboard menu * [APP-1603] Add dashboard menu * [APP-1603] Add dashboard menu * [APP-1603] Add dashboard menu * Bug/app 1607 (#311) * Fix: Update stats calculation logic [APP-1607] * Fix: Set fixed width for the results table [APP-1650] * Fix: Update filter rules [APP-1634] * New: Add the no search results state [APP-1651] * Fix: Convert indents [n/a] * [APP-1670] add menu on Manage Fixes (#315) * [APP-1670] add menu on Manage Fixes * [APP-1670] update menu * [APP-1611] fix comments * fix: direction of snippet (#313) * [APP-1561] New menu layout (#308) * update: app menu and layout * merge: latest changes from feature/remediation * add: alert indicator to the closed sidebar * fix: page layout for statement page * update: menu display names * fix: topbar menu layout * update: sidebar menu width * update: sidebar menu width * fix: popup menu layout * add: hover action to the toggle button * update: my account menu * fix: quota indicator for closed sidebar * fix: icon alignments * fix: scroll behaviour * fix: page scroll behaviour * fix: popup menu hover state * update: quota bar and group layouts * add: tooltips to the menu items * update: make scans page fixed height and scrollable * update: styles with theme references and added new styled components * fix: make sidebar smoother * update: accessibility page heading * Merge latest develop * [APP-1611] trigger save entry for clean cache (#314) * [APP-1611] trigger save entry for clean cache * [APP-1611] fix comments * [APP-1611] fix comments * [APP-1611] fix comments * [APP-1611] fix comments * [APP-0000] call trigger save async (#319) * [APP-1611] trigger save entry for clean cache * [APP-1611] fix comments * [APP-1611] fix comments * [APP-1611] fix comments * [APP-1611] fix comments * [APP-0000] call trigger save async * fix: scrollbar issues (#318) * [APP-1615] add remediation for wp image (#321) * POC - FrontEnd remediations to handle Dynamic Data [APP-1644] (#312) * POC - FrontEnd remediations to handle Dynamic Data * Update modules/remediation/components/remediation-runner.php Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * added MutationObserver to cover elements that are added later on the page runs until remediations are all done, and disconnect * added $use_frontend flag instead of using "false" * Update modules/remediation/components/remediation-runner.php Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * WIP on poc/fe-remediations * [APP-0000] call trigger save async * [APP-1644] apply FE remediation * [APP-1644] apply FE remediation * [APP-1644] apply FE remediation * Add timeout (wait for FE remediation timeout) * Add timeout (wait for FE remediation timeout) * Add timeout (wait for FE remediation timeout) * Add timeout (wait for FE remediation timeout) * Add timeout (wait for FE remediation timeout) * Small fixes * Small fixes * Small fixes * Small fixes --------- Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> Co-authored-by: vasyldinets <vasyld@elementor.red> * [APP-1611] Fix cache issue (#324) * [APP-1611] trigger save entry for clean cache * [APP-1611] fix comments * [APP-1611] fix comments * [APP-1611] fix comments * [APP-1611] fix comments * [APP-0000] call trigger save async * [APP-1611] clear cache * [APP-1657] upgrade cta (#323) * update: added logic to show button based on plan * Update modules/settings/assets/js/components/quota-bar/quota-bar-group.js Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * fix: eslint error --------- Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com> * [APP-1658] Update accessibility admin column design (#322) * update: wpadmin column layout * update: move icon to assets * Fix: Resolve remediation encoding issue [APP-1646] (#325) --------- Co-authored-by: Ohad <ohad@elementor.com> Co-authored-by: Raz Ohad <admin@bainternet.info> Co-authored-by: Nirbhay Singh <121793120+nirbhayel@users.noreply.github.com> Co-authored-by: Pavlo Kniazevych <139438463+pkniazevych@users.noreply.github.com> Co-authored-by: gitstream-cm[bot] <111687743+gitstream-cm[bot]@users.noreply.github.com>
285 lines
7.4 KiB
PHP
285 lines
7.4 KiB
PHP
<?php
|
|
|
|
namespace EA11y\Classes\Services;
|
|
|
|
use EA11y\Modules\Connect\Classes\Data;
|
|
use EA11y\Modules\Connect\Classes\Exceptions\Service_Exception;
|
|
use EA11y\Modules\Connect\Classes\Service;
|
|
use EA11y\Modules\Connect\Module as Connect;
|
|
use Exception;
|
|
use Throwable;
|
|
use WP_Error;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit; // Exit if accessed directly.
|
|
}
|
|
|
|
/**
|
|
* Class Client
|
|
*/
|
|
class Client {
|
|
private const BASE_URL = 'https://my.elementor.com/apps/api/v1/a11y/';
|
|
|
|
private bool $refreshed = false;
|
|
|
|
public static ?Client $instance = null;
|
|
|
|
/**
|
|
* set_instance
|
|
* used for testing
|
|
* @param $instance
|
|
*/
|
|
public static function set_instance( $instance ) {
|
|
self::$instance = $instance;
|
|
}
|
|
|
|
/**
|
|
* get_instance
|
|
* @return Client|null
|
|
*/
|
|
public static function get_instance(): ?Client {
|
|
if ( ! self::$instance ) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function get_site_info(): array {
|
|
return [
|
|
// Which API version is used.
|
|
'app_version' => EA11Y_VERSION,
|
|
// Which language to return.
|
|
'site_lang' => get_bloginfo( 'language' ),
|
|
// site to connect
|
|
'site_url' => trailingslashit( home_url() ),
|
|
// current user
|
|
'local_id' => get_current_user_id(),
|
|
// User Agent
|
|
'user_agent' => ! empty( $_SERVER['HTTP_USER_AGENT'] )
|
|
? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) )
|
|
: 'Unknown',
|
|
'webhook_url' => self::webhook_endpoint(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Log update endpoint
|
|
* @return string
|
|
*/
|
|
private static function webhook_endpoint(): string {
|
|
$blog_id = get_current_blog_id();
|
|
return get_rest_url( $blog_id, 'a11y/v1/webhooks/common' );
|
|
}
|
|
|
|
public function make_request( $method, $endpoint, $body = [], array $headers = [], $send_json = false, $file = false, $file_name = '' ) {
|
|
$headers = array_replace_recursive( [
|
|
'x-elementor-a11y' => EA11Y_VERSION,
|
|
'x-elementor-apps' => 'a11y',
|
|
], $headers );
|
|
|
|
$headers = array_replace_recursive(
|
|
$headers,
|
|
$this->is_connected() ? $this->generate_authentication_headers( $endpoint ) : []
|
|
);
|
|
|
|
$body = array_replace_recursive( $body, $this->get_site_info() );
|
|
|
|
if ( $send_json ) {
|
|
$headers['Content-Type'] = 'application/json; charset=utf-8';
|
|
$body = wp_json_encode( $body );
|
|
}
|
|
try {
|
|
if ( $file ) {
|
|
$boundary = wp_generate_password( 24, false );
|
|
$body = $this->get_upload_request_body( $body, $file, $boundary, $file_name );
|
|
// add content type header
|
|
$headers['Content-Type'] = 'multipart/form-data; boundary=' . $boundary;
|
|
}
|
|
} catch ( Throwable $t ) {
|
|
return new WP_Error( 500, $t->getMessage() );
|
|
}
|
|
|
|
return $this->request(
|
|
$method,
|
|
$endpoint,
|
|
[
|
|
'timeout' => 100,
|
|
'headers' => $headers,
|
|
'body' => $body,
|
|
]
|
|
);
|
|
}
|
|
|
|
public static function get_client_base_url() {
|
|
return apply_filters( 'ea11y_client_base_url', self::BASE_URL );
|
|
}
|
|
|
|
private static function get_remote_url( $endpoint ): string {
|
|
return self::get_client_base_url() . $endpoint;
|
|
}
|
|
|
|
protected function is_connected(): bool {
|
|
return Connect::is_connected();
|
|
}
|
|
|
|
public function add_bearer_token( $headers ) {
|
|
if ( $this->is_connected() ) {
|
|
$headers['Authorization'] = 'Bearer ' . Data::get_access_token();
|
|
}
|
|
return $headers;
|
|
}
|
|
|
|
protected function generate_authentication_headers( $endpoint ): array {
|
|
$headers = [
|
|
'endpoint' => $endpoint,
|
|
];
|
|
|
|
return $this->add_bearer_token( $headers );
|
|
}
|
|
|
|
/**
|
|
* @throws Service_Exception
|
|
*/
|
|
protected function request( $method, $endpoint, $args = [] ) {
|
|
$args['method'] = $method;
|
|
|
|
$response = wp_remote_request(
|
|
self::get_remote_url( $endpoint ),
|
|
$args
|
|
);
|
|
|
|
if ( is_wp_error( $response ) ) {
|
|
$message = $response->get_error_message();
|
|
|
|
return new WP_Error(
|
|
$response->get_error_code(),
|
|
is_array( $message ) ? join( ', ', $message ) : $message
|
|
);
|
|
}
|
|
|
|
$body = wp_remote_retrieve_body( $response );
|
|
$response_code = (int) wp_remote_retrieve_response_code( $response );
|
|
|
|
if ( ! $response_code ) {
|
|
return new WP_Error( 500, 'No Response' );
|
|
}
|
|
|
|
// Server sent a success message without content.
|
|
if ( 'null' === $body ) {
|
|
$body = true;
|
|
}
|
|
|
|
// Return with no content on successful deletion of domain from service.
|
|
if ( 204 === $response_code ) {
|
|
$body = true;
|
|
return $body;
|
|
}
|
|
|
|
$body = json_decode( $body );
|
|
|
|
if ( false === $body ) {
|
|
return new WP_Error( 422, 'Wrong Server Response' );
|
|
}
|
|
|
|
// If the token is invalid, refresh it and try again once only.
|
|
if ( ! $this->refreshed && ! empty( $body->message ) && ( false !== strpos( $body->message, 'Invalid Token' ) ) ) {
|
|
Service::refresh_token();
|
|
$this->refreshed = true;
|
|
$args['headers'] = $this->add_bearer_token( $args['headers'] );
|
|
return $this->request( $method, $endpoint, $args );
|
|
}
|
|
|
|
// If there is mismatch then trigger the mismatch flow explicitly.
|
|
if ( ! $this->refreshed && ! empty( $body->message ) && ( false !== strpos( $body->message, 'site url mismatch' ) ) ) {
|
|
Data::set_home_url( 'https://wrongurl' );
|
|
return new WP_Error( 401, 'site url mismatch' );
|
|
}
|
|
|
|
if ( ! in_array( $response_code, [ 200, 201 ], true ) ) {
|
|
// In case $as_array = true.
|
|
$message = $body->message ?? wp_remote_retrieve_response_message( $response );
|
|
$message = is_array( $message ) ? join( ', ', $message ) : $message;
|
|
$code = isset( $body->code ) ? (int) $body->code : $response_code;
|
|
|
|
return new WP_Error( $code, $message );
|
|
}
|
|
|
|
return $body;
|
|
}
|
|
|
|
/**
|
|
* get_site_data
|
|
* @return mixed|WP_Error Site data
|
|
*/
|
|
public static function get_site_data() {
|
|
return self::get_instance()->make_request( 'POST', 'stats' );
|
|
}
|
|
|
|
/**
|
|
* register_website
|
|
* @return mixed|WP_Error Site data
|
|
*/
|
|
public static function register_website() {
|
|
return self::get_instance()->make_request( 'POST', 'site' );
|
|
}
|
|
|
|
/**
|
|
* get_upload_request_body
|
|
*
|
|
* @param array $body
|
|
* @param $file
|
|
* @param string $boundary
|
|
* @param string $file_name
|
|
*
|
|
* @return string
|
|
* @throws Exception
|
|
*/
|
|
private function get_upload_request_body( array $body, $file, string $boundary, string $file_name = '' ): string {
|
|
$payload = '';
|
|
// add all body fields as standard POST fields:
|
|
foreach ( $body as $name => $value ) {
|
|
$payload .= '--' . $boundary;
|
|
$payload .= "\r\n";
|
|
$payload .= 'Content-Disposition: form-data; name="' . esc_attr( $name ) . '"' . "\r\n\r\n";
|
|
$payload .= $value;
|
|
$payload .= "\r\n";
|
|
}
|
|
|
|
$image_mime = image_type_to_mime_type( exif_imagetype( $file ) );
|
|
|
|
if ( empty( $file_name ) ) {
|
|
$file_name = basename( $file );
|
|
}
|
|
|
|
$payload .= $this->get_file_payload( $file_name, $image_mime, $file, $boundary );
|
|
|
|
$payload .= '--' . $boundary . '--';
|
|
|
|
return $payload;
|
|
}
|
|
|
|
/**
|
|
* get_file_payload
|
|
* @param string $filename
|
|
* @param string $file_type
|
|
* @param string $file_path
|
|
* @param string $boundary
|
|
* @return string
|
|
*/
|
|
private function get_file_payload( string $filename, string $file_type, string $file_path, string $boundary ): string {
|
|
$name = $filename ?? basename( $file_path );
|
|
$mine_type = 'image' === $file_type ? image_type_to_mime_type( exif_imagetype( $file_path ) ) : $file_type;
|
|
|
|
$payload = '';
|
|
// Upload the file
|
|
$payload .= '--' . $boundary;
|
|
$payload .= "\r\n";
|
|
$payload .= 'Content-Disposition: form-data; name="image"; filename="' . esc_attr( $name ) . '"' . "\r\n";
|
|
$payload .= 'Content-Type: ' . $mine_type . "\r\n";
|
|
$payload .= "\r\n";
|
|
$payload .= file_get_contents( $file_path );
|
|
$payload .= "\r\n";
|
|
|
|
return $payload;
|
|
}
|
|
}
|