* @return Affilizz\Core An instance of the current class. */ public static function get_instance() { if ( ! isset( self::$instance ) ) { self::$instance = new self(); } return self::$instance; } /** * Creates an instance of the current class. * @author Affilizz * @return void */ public function __construct() { // Register the global variables define( 'AFFILIZZ_DIRECTORY', trailingslashit( WP_CONTENT_DIR . '/plugins/affilizz/' ) ); define( 'AFFILIZZ_URL', trailingslashit( esc_url( WP_CONTENT_URL ) . '/plugins/affilizz/' ) ); // Register the environment specifics defined( 'AFFILIZZ_SSR_ENDPOINT_ROOT' ) || define( 'AFFILIZZ_SSR_ENDPOINT_ROOT', 'https://rendering.ssr.affilizz.com/' ); defined( 'AFFILIZZ_SSR_DEFAULT_WIDTH' ) || define( 'AFFILIZZ_SSR_DEFAULT_WIDTH', '740' ); defined( 'AFFILIZZ_USER_API_BASE_URL' ) || define( 'AFFILIZZ_USER_API_BASE_URL', 'https://user.api.affilizz.com/api/v1/' ); defined( 'AFFILIZZ_CMS_API_BASE_URL' ) || define( 'AFFILIZZ_CMS_API_BASE_URL', 'https://publication-cms.api.affilizz.com/api/v1/' ); defined( 'AFFILIZZ_API_KEY_HELP_URL' ) || define( 'AFFILIZZ_API_KEY_HELP_URL', 'https://intercom-help.eu/affilizz/fr/articles/26097-ou-trouver-ma-cle-d-api-pour-wordpress' ); defined( 'AFFILIZZ_PUBLICATIONS_TABLE' ) || define( 'AFFILIZZ_PUBLICATIONS_TABLE', 'affilizz_publications' ); defined( 'AFFILIZZ_API_HTTP_TIMEOUT' ) || define( 'AFFILIZZ_API_HTTP_TIMEOUT', 45 ); defined( 'AFFILIZZ_API_URL_PATTERN' ) || define( 'AFFILIZZ_API_URL_PATTERN', '/^(http|https):\/\/[^ "]+[^.]$/' ); // URLS on the Affilizz Dashboard defined( 'AFFILIZZ_CREATE_PUBLICATION_URL' ) || define( 'AFFILIZZ_CREATE_PUBLICATION_URL', 'https://app.affilizz.com/publications/new' ); defined( 'AFFILIZZ_EDIT_PUBLICATION_URL' ) || define( 'AFFILIZZ_EDIT_PUBLICATION_URL', 'https://app.affilizz.com/publications/##publication##?mediaId=##media##' ); // Deal with issues loading from a CDN defined( 'AFFILIZZ_CDN_RENDERING_SCRIPT_LOCATION' ) || define( 'AFFILIZZ_CDN_RENDERING_SCRIPT_LOCATION', 'https://sc.affilizz.com/affilizz.js' ); defined( 'AFFILIZZ_CDN_RENDERING_STYLE_LOCATION' ) || define( 'AFFILIZZ_CDN_RENDERING_STYLE_LOCATION', '' ); defined( 'AFFILIZZ_CDN_CACHE_TIME' ) || define( 'AFFILIZZ_CDN_CACHE_TIME', DAY_IN_SECONDS ); defined( 'AFFILIZZ_CDN_CACHE_ROOT_PATH' ) || define( 'AFFILIZZ_CDN_CACHE_ROOT_PATH', WP_CONTENT_DIR . '/cache/' ); defined( 'AFFILIZZ_CDN_CACHE_ROOT_URL' ) || define( 'AFFILIZZ_CDN_CACHE_ROOT_URL', WP_CONTENT_URL . '/cache/' ); // Display defaults defined( 'AFFILIZZ_LATEST_PUBLICATIONS_COUNT' ) || define( 'AFFILIZZ_LATEST_PUBLICATIONS_COUNT', 5 ); // Affilizz defaults defined( 'AFFILIZZ_DEFAULT_RENDERING_MODE' ) || define( 'AFFILIZZ_DEFAULT_RENDERING_MODE', 'webcomponent' ); // The "s" modifier lets the match span the multi-line SSR fragments of the hybrid mode defined( 'AFFILIZZ_SELECTIVE_ENQUEUING_REGEX' ) || define( 'AFFILIZZ_SELECTIVE_ENQUEUING_REGEX', '|\(.*?)\<\/affilizz-rendering|s' ); defined( 'AFFILIZZ_DELETE_TABLE_CONFIRMATION_TEXT' ) || define( 'AFFILIZZ_DELETE_TABLE_CONFIRMATION_TEXT', 'CONFIRM-AFFILIZZ-TABLE-DELETION' ); defined( 'AFFILIZZ_API_DEFAULT_COUNTRY_CODE' ) || define( 'AFFILIZZ_API_DEFAULT_COUNTRY_CODE', 'FR' ); defined( 'AFFILIZZ_DEFAULT_API_CHECK_CYCLE_DURATION' ) || define( 'AFFILIZZ_DEFAULT_API_CHECK_CYCLE_DURATION', 2 * DAY_IN_SECONDS ); // Local caching defined( 'AFFILIZZ_PUBLICATIONS_TRANSIENT_KEY' ) || define( 'AFFILIZZ_PUBLICATIONS_TRANSIENT_KEY', 'affilizz-initial-publications-collection' ); // SSR fragments of the hybrid rendering mode defined( 'AFFILIZZ_FRAGMENT_TTL' ) || define( 'AFFILIZZ_FRAGMENT_TTL', HOUR_IN_SECONDS ); defined( 'AFFILIZZ_FRAGMENT_MINIMUM_TTL' ) || define( 'AFFILIZZ_FRAGMENT_MINIMUM_TTL', 5 * MINUTE_IN_SECONDS ); defined( 'AFFILIZZ_FRAGMENT_HTTP_TIMEOUT' ) || define( 'AFFILIZZ_FRAGMENT_HTTP_TIMEOUT', 3 ); // Register and enqueue admin specific styles and scripts add_action( 'admin_enqueue_scripts', array( $this, 'admin_register_assets' ) ); // Iframe-aware enqueue for block-editor pages (silences WP's "added // to the iframe incorrectly" warning by going through the proper // hook). Registration of the handles still happens in // admin_register_assets — this hook only enqueues. add_action( 'enqueue_block_assets', array( $this, 'enqueue_block_editor_styles' ) ); // Load the plugin's translations and start the plugin add_action( 'init', array( $this, 'init' ), 99 ); // Change the administration footer output add_action( 'admin_footer', array( $this, 'admin_footer' ), 99 ); // Deal with the timeout, globally, for Afilizz (or assimilated) related requests add_filter( 'http_request_timeout', array( $this, 'force_http_request_timeout' ), 10, 2 ); // Add analytics information for debug add_action( 'init', function () { $affilizz_javascript_debug_mode = get_option( 'affilizz_javascript_debug_mode' ); if ( $affilizz_javascript_debug_mode ) { add_filter( 'affilizz_publications_javascript_l10n', function ( $l10n ) { $l10n['affilizz_analytics'] = is_admin() && current_user_can( 'manage_options' ) ? Util\Analytics::all() : array(); return $l10n; } ); } } ); // The Gutenberg utilitary class hooks on the init action new Editor\Gutenberg(); } /** * Hooks after the plugin load process to allow for translation in later hooks. * @author Affilizz * @return void */ public function init() { new Install(); // Add the custom admin pages Page\Settings::get_instance(); new Page\Wizard(); // Add the shortcodes Shortcode\Publication::get_instance(); // Add the utilitary classes Util\Filters::get_instance(); Util\Assets::get_instance(); Util\Notices::get_instance(); Util\Editor::get_instance(); Util\Fragments::get_instance(); Util\Rocket::get_instance(); Ajax::get_instance(); // Add the custom editor blocks Editor\Classic::get_instance(); } /** * Load plugin translations. * @author Affilizz * @return void */ public function load_translations() { load_textdomain( 'affilizz', AFFILIZZ_DIRECTORY . 'languages/affilizz-' . get_locale() . '.mo' ); // Allows translation of the plugin name __( 'Affilizz', 'affilizz' ); __( 'Affilizz allows you to manage all your affiliated content in one place regardless of your activity.', 'affilizz' ); } /** * Allows the plugin to autoload the classes it holds. * @param $class The name of the class to load, namespaced. * @author Affilizz * @return void */ public static function autoload( $class = '' ) { // Deal with the filename structure $class = str_replace( __NAMESPACE__ . '\\', '', $class ); $segments = explode( '\\', $class ); $path = __DIR__ . '/' . implode( '/', $segments ) . '.php'; // If the correct path exists, use it if ( file_exists( $path ) ) { include $path; return; } // If the lowercase version exists, use it if ( file_exists( strtolower( $path ) ) ) { include $path; } return false; } /** * Register scripts and stylesheets for the administration area. * @author Affilizz * @return void */ public function admin_register_assets( $hook_suffix = null ) { wp_enqueue_editor(); // Add custom scripts wp_register_script( 'affilizz-admin', esc_url( AFFILIZZ_URL ) . 'assets/dist/js/admin.js', array(), esc_attr( AFFILIZZ_ASSETS_BUILD_VERSION ), true ); wp_register_script( 'tom-select', esc_url( AFFILIZZ_URL ) . 'assets/vendor/tom-select/tom-select.complete.min.js', array(), esc_attr( AFFILIZZ_ASSETS_BUILD_VERSION ), true ); wp_register_script( 'affilizz-admin-react-components', esc_url( AFFILIZZ_URL ) . 'assets/dist/components/affilizz-embed/affilizz.js', array(), esc_attr( AFFILIZZ_ASSETS_BUILD_VERSION ), true ); // Add PHP variables to the JS scripts, for translation or display purposes $this->load_translations(); wp_localize_script( 'affilizz-admin', 'affilizz_l10n', $this->get_javascript_l10n() ); // Enqueue the scripts, the WordPress way wp_enqueue_script( 'affilizz-admin' ); wp_enqueue_script( 'tom-select' ); wp_enqueue_script( 'affilizz-admin-react-components' ); // Do not load the editor in the wizard if ( in_array( $hook_suffix, array( 'post.php', 'post-new.php' ), true ) ) { wp_enqueue_script( 'jquery-ui-core' ); wp_enqueue_script( 'jquery-ui-sortable' ); wp_enqueue_script( 'affilizz-admin-editor-classic' ); wp_enqueue_script( 'affilizz-rendering', ( Assets::get_instance() )->get_diverted_js_file_url(), array(), ( Assets::get_instance() )->get_diverted_js_file_version(), array( 'strategy' => 'defer' ) ); } // Register custom styles. Enqueueing of these is split between two // hooks below: non-block-editor admin pages go through this hook, // block-editor pages go through enqueue_block_assets so WP marks // them as iframe-aware (avoiding a console warning when WP's iframe // loader copies parent admin styles). wp_register_style( 'affilizz-admin', esc_url( AFFILIZZ_URL ) . 'assets/dist/css/admin.css', '', AFFILIZZ_ASSETS_BUILD_VERSION ); wp_register_style( 'tom-select', esc_url( AFFILIZZ_URL ) . 'assets/vendor/tom-select/tom-select.default.css', '', AFFILIZZ_ASSETS_BUILD_VERSION ); if ( ! self::is_block_editor_screen() ) { wp_enqueue_style( 'affilizz-admin' ); wp_enqueue_style( 'tom-select' ); } } /** * True when the current admin request is rendering the block editor * (post editor, site editor, widget editor). Used to gate styles between * the regular admin enqueue hook and enqueue_block_assets. * @return bool */ private static function is_block_editor_screen() { if ( ! function_exists( 'get_current_screen' ) ) { return false; } $screen = get_current_screen(); return $screen && method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor(); } /** * Iframe-aware enqueue for admin styles needed inside the block editor * (the picker modal lives in the parent frame and uses these styles). * Enqueuing here marks the stylesheets so WP's iframe loader stops * warning that they were added incorrectly. Self-registers in case this * hook runs before admin_register_assets. * @return void */ public function enqueue_block_editor_styles() { if ( ! is_admin() ) { return; } wp_enqueue_style( 'affilizz-admin', esc_url( AFFILIZZ_URL ) . 'assets/dist/css/admin.css', array(), AFFILIZZ_ASSETS_BUILD_VERSION ); wp_enqueue_style( 'tom-select', esc_url( AFFILIZZ_URL ) . 'assets/vendor/tom-select/tom-select.default.css', array(), AFFILIZZ_ASSETS_BUILD_VERSION ); } /** * Outputs the HTML for the footer section of the admin panel. * @author Romain Carlier * @return void */ public function admin_footer() { // Enable the modal only if we are in Classic Editor context include_once trailingslashit( AFFILIZZ_DIRECTORY ) . 'templates/administration/partial/footer.php'; } /** * Filtreable getter for the Affilizz API publications transient. * @author Affilizz * @since 1.14.0 * @return String The API publications transient, (potentially) filtered. */ public static function get_publications_transient_key() { return apply_filters( 'affilizz_publications_transient_key', AFFILIZZ_PUBLICATIONS_TRANSIENT_KEY ); } /** * Register scripts and stylesheets for the administration area. * @author Affilizz * @return void */ public static function regenerate_uuid() { $previous_affilizz_proxy_uuid = get_option( 'affilizz_proxy_uuid' ); $updated_affilizz_proxy_uuid = wp_generate_uuid4(); update_option( 'affilizz_proxy_uuid', $updated_affilizz_proxy_uuid ); ( self::get_instance() )->refresh_cache_directory( $previous_affilizz_proxy_uuid ); return $updated_affilizz_proxy_uuid; } /** * The plugin is removed, remove its traces. * @author Affilizz * @return void */ public static function uninstall() { // Transients delete_transient( 'affilizz_should_display_install_wizard' ); // SSR fragments of the hybrid rendering mode Install::drop_fragments_table(); delete_option( Util\Fragments::BACKFILL_OPTION ); wp_clear_scheduled_hook( Util\Fragments::BACKFILL_HOOK ); } /** * Creates the cache folders for our local files. * @author Affilizz * @since 1.12.0 * @return void */ public function init_cache_directories() { // Create cache folder if it does not exist if ( ! is_dir( self::get_cdn_cache_root_path() ) ) { wp_mkdir_p( self::get_cdn_cache_root_path() ); } } /** * Deletes recursively the content of a folder, replaces previous call to $wp_filesystem->delete. * @author Affilizz * @since 1.12.0 * @return void */ private function delete_directory( $directory ) { // Avoid deleting files in other directories than this one $cache_root = realpath( self::get_cdn_cache_root_path() ); $directory_path = realpath( $directory ); if ( false === $cache_root || false === $directory_path || stripos( $directory_path, $cache_root ) !== 0 ) { return false; } // Assign files inside the directory $directory_iterator = new \DirectoryIterator( $directory_path ); // Remove all the files in the list foreach ( $directory_iterator as $file_information ) { if ( $file_information->isDot() || ! $file_information->isFile() ) { continue; } wp_delete_file( $file_information->getPathname() ); } // Finally, remove the (now empty) directory global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once ABSPATH . 'wp-admin/includes/file.php'; WP_Filesystem(); } $wp_filesystem->rmdir( $directory_path ); } /** * Create or update the local cache directory. * @author Affilizz * @since 1.12.0 * @return void */ public function refresh_cache_directory( $previous_uuid = '' ) { $affilizz_proxy_uuid = get_option( 'affilizz_proxy_uuid' ); $new_cache_folder_path = trailingslashit( self::get_cdn_cache_root_path() ) . $affilizz_proxy_uuid; // Delete the previous directory if it exists if ( ! empty( $previous_uuid ) && is_dir( trailingslashit( self::get_cdn_cache_root_path() ) . $previous_uuid ) ) { $this->delete_directory( trailingslashit( self::get_cdn_cache_root_path() ) . $previous_uuid ); } // Create new cache folder if it does not exist if ( ! is_dir( $new_cache_folder_path ) ) { wp_mkdir_p( $new_cache_folder_path ); } } /** * Filtreable getter for the Affilizz SSR Endpoint. * @author Affilizz * @since 1.13.0 * @return String The SSR Endpoint, (potentially) filtered. */ public static function get_ssr_endpoint_root() { return apply_filters( 'affilizz_ssr_endpoint_root_url', AFFILIZZ_SSR_ENDPOINT_ROOT ); } /** * Filtreable getter for the Affilizz rendering mode, either generic or for a specific publication. * @author Affilizz * @since 1.13.0 * @param $affilizz_publication_id The Affilizz publication ID to pass to the filter. * @return String The rendering mode, either generic or for a specific publication, (potentially) filtered. */ public static function get_rendering_mode( $affilizz_publication_id = 0 ) { return apply_filters( 'affilizz_rendering_mode', AFFILIZZ_DEFAULT_RENDERING_MODE, $affilizz_publication_id ) ?? 'webcomponent'; } /** * Returns the rendering mode in use : the one chosen in the settings, or else the (filtered) default one. * The former "ssr" mode is served by the "hybrid" mode. * @author Affilizz * @since 1.18.0 * @param $affilizz_publication_id The Affilizz publication ID to pass to the filter. * @return String Either "webcomponent" or "hybrid" (or a custom value from the filter). */ public static function get_current_rendering_mode( $affilizz_publication_id = 0 ) { $rendering_mode = get_option( 'affilizz_rendering_mode' ); if ( ! $rendering_mode || ! in_array( $rendering_mode, array( 'ssr', 'hybrid', 'webcomponent' ), true ) ) { $rendering_mode = self::get_rendering_mode( $affilizz_publication_id ); } return ( 'ssr' === $rendering_mode ) ? 'hybrid' : $rendering_mode; } /** * Filtreable getter for the time after which a stored SSR fragment is refreshed (hybrid rendering mode). * @author Affilizz * @since 1.18.0 * @return Integer The duration in seconds, (potentially) filtered, never under AFFILIZZ_FRAGMENT_MINIMUM_TTL. */ public static function get_fragment_ttl() { $ttl_in_minutes = (int) get_option( 'affilizz_fragment_ttl' ); $ttl = $ttl_in_minutes > 0 ? $ttl_in_minutes * MINUTE_IN_SECONDS : AFFILIZZ_FRAGMENT_TTL; return max( AFFILIZZ_FRAGMENT_MINIMUM_TTL, (int) apply_filters( 'affilizz_fragment_ttl', $ttl ) ); } /** * Filtreable getter for the HTTP timeout of the SSR fragment requests, made after the response is sent. * @author Affilizz * @since 1.18.0 * @return Integer The timeout in seconds, (potentially) filtered. */ public static function get_fragment_http_timeout() { return max( 1, (int) apply_filters( 'affilizz_fragment_http_timeout', AFFILIZZ_FRAGMENT_HTTP_TIMEOUT ) ); } /** * Filtreable getter for the Affilizz rendering mode, either generic or for a specific publication. * @author Affilizz * @since 1.13.0 * @param $affilizz_publication_id The Affilizz publication ID to pass to the filter. * @return String The rendering mode, either generic or for a specific publication, (potentially) filtered. */ public static function get_publication_default_width( $affilizz_publication_id = 0 ) { return apply_filters( 'affilizz_publication_default_width', AFFILIZZ_SSR_DEFAULT_WIDTH, $affilizz_publication_id ) ?? 'webcomponent'; } /** * Filtreable getter for the Affilizz rendering script location URL. * @author Affilizz * @since 1.13.0 * @return String The rendering script location URL, (potentially) filtered. */ public static function get_rendering_script_location() { return apply_filters( 'affilizz_cdn_rendering_script_location', AFFILIZZ_CDN_RENDERING_SCRIPT_LOCATION ); } /** * Filtreable getter for the Affilizz distant CSS file location URL. * @author Affilizz * @since 1.13.0 * @return String The rendering script location URL, (potentially) filtered. */ public static function get_rendering_style_location() { return apply_filters( 'affilizz_cdn_rendering_style_location', AFFILIZZ_CDN_RENDERING_STYLE_LOCATION ); } /** * Filtreable getter for the Affilizz CDN caching time. * @author Affilizz * @since 1.13.0 * @return String The CDN caching time, (potentially) filtered. */ public static function get_cdn_cache_time() { return apply_filters( 'affilizz_cdn_cache_time', AFFILIZZ_CDN_CACHE_TIME ); } /** * Filtreable getter for the Affilizz CDN caching root path. * @author Affilizz * @since 1.13.0 * @return String The CDN caching root path, (potentially) filtered. */ public static function get_cdn_cache_root_path() { return apply_filters( 'affilizz_cdn_cache_root_path', AFFILIZZ_CDN_CACHE_ROOT_PATH ); } /** * Filtreable getter for the Affilizz CDN caching root URL. * @author Affilizz * @since 1.13.0 * @return String The CDN caching root URL, (potentially) filtered. */ public static function get_cdn_cache_root_url() { return apply_filters( 'affilizz_cdn_cache_root_url', AFFILIZZ_CDN_CACHE_ROOT_URL ); } /** * Filtreable getter for the Affilizz CDN caching root URL. * @author Affilizz * @since 1.13.0 * @return String The CDN caching root URL, (potentially) filtered. */ public static function get_publications_database_table() { return apply_filters( 'affilizz_publications_database_table', AFFILIZZ_PUBLICATIONS_TABLE ); } /** * Filtreable getter for the Affilizz API calls HTTP timeout. * @author Affilizz * @since 1.15.0 * @return String The API calls HTTP timeout, (potentially) filtered. */ public static function get_api_http_timeout() { return max( 5, (int) apply_filters( 'affilizz_api_http_timeout', AFFILIZZ_API_HTTP_TIMEOUT ) ); } /** * Filtreable getter for the Affilizz API regular expression pattern for URLs. * @author Affilizz * @since 1.15.0 * @return String The API regular expression pattern for URLs, (potentially) filtered. */ public static function get_api_url_pattern() { return apply_filters( 'affilizz_api_url_pattern', AFFILIZZ_API_URL_PATTERN ); } /** * Filtreable getter for the Affilizz selective enqueuing regular expression. * @author Affilizz * @since 1.13.0 * @return String The selective enqueuing regular expression, (potentially) filtered. */ public static function get_selective_enqueuing_regex() { return apply_filters( 'affilizz_selective_enqueuing_regex', AFFILIZZ_SELECTIVE_ENQUEUING_REGEX, false ); } /** * Filtreable getter for the Affilizz default API country code. * @author Affilizz * @since 1.13.0 * @return String The country code, (potentially) filtered. */ public static function get_api_country_code() { return apply_filters( 'affilizz_api_country_code', get_option( 'affilizz_api_country_code', AFFILIZZ_API_DEFAULT_COUNTRY_CODE ) ) ?? 'FR'; } /** * Filtreable getter for the Affilizz publication check cycle (API). * @author Affilizz * @since 1.13.0 * @return String The duration, (potentially) filtered. */ public static function get_api_check_cycle_duration() { return apply_filters( 'affilizz_api_check_cycle_duration', AFFILIZZ_DEFAULT_API_CHECK_CYCLE_DURATION ); } /** * Filtreable getter for the number of items at the top of the default suggestion list. * @author Affilizz * @since 1.15.5 * @return String The count, (potentially) filtered. */ public static function get_suggested_latest_publications_count() { return apply_filters( 'affilizz_latest_publications_count', AFFILIZZ_LATEST_PUBLICATIONS_COUNT ); } /** * Returns a list of allowed / needed HTML tags for the configuration pages. * @author Affilizz * @return Array A list of allowed / needed HTML tags for the configuration pages. */ public static function get_extended_allowed_tags() { global $allowedtags; return array_merge( array( 'form' => array( 'action' => true, 'method' => true, 'class' => true, 'id' => true, ), 'select' => array( 'name' => true, 'multiple' => true, 'placeholder' => true, 'autocomplete' => true, 'disabled' => true, 'class' => true, 'id' => true, ), 'option' => array( 'name' => true, 'value' => true, 'placeholder' => true, 'autocomplete' => true, 'disabled' => true, 'class' => true, 'id' => true, 'selected' => 'true', ), 'input' => array( 'name' => true, 'placeholder' => true, 'autocomplete' => true, 'disabled' => true, 'class' => true, 'id' => true, 'type' => true, 'value' => true, 'selected' => true, 'checked' => true, ), 'textarea' => array( 'name' => true, 'placeholder' => true, 'autocomplete' => true, 'disabled' => true, 'class' => true, 'id' => true, ), 'label' => array( 'for' => true, 'class' => true, 'id' => true, ), 'button' => array( 'type' => true, 'class' => true, 'id' => true, 'name' => true, 'style' => true, ), 'script' => array( 'type' => true, 'id' => true, ), 'style' => array( 'type' => true, ), 'div' => array( 'class' => true, 'id' => true, 'style' => true, ), 'section' => array( 'class' => true, 'id' => true, ), 'svg' => array( 'class' => true, 'role' => true, 'xmlns' => true, 'width' => true, 'height' => true, 'viewbox' => true, ), 'g' => array( 'fill' => true, ), 'title' => array( 'title' => true, ), 'path' => array( 'd' => true, 'fill' => true, ), 'nav' => array( 'class' => true, 'id' => true, ), 'footer' => array( 'class' => true, 'id' => true, ), 'header' => array( 'class' => true, 'id' => true, ), 'ol' => array( 'class' => true, ), 'ul' => array( 'class' => true, ), 'li' => array( 'class' => true, 'id' => true, ), 'fieldset' => array(), 'legend' => array(), 'a' => array( 'title' => true, 'href' => true, 'class' => true, 'id' => true, 'data-hide-text' => true, 'data-show-text' => true, ), 'span' => array( 'class' => true, 'id' => true, ), 'small' => array( 'class' => true, 'id' => true, ), 'strong' => array( 'class' => true, 'id' => true, ), 'p' => array( 'class' => true, 'id' => true, 'style' => true, ), 'h2' => array( 'class' => true, 'id' => true, ), 'h3' => array( 'class' => true, 'id' => true, ), 'h4' => array( 'class' => true, 'id' => true, ), 'img' => array( 'src' => true, 'width' => true, 'alt' => true, 'class' => true, 'id' => true, ), ) ); } /** * Returns an array of localized strings that can be used in javascript files. * @author Affilizz * @return Array An array of localized strings that can be used in javascript files. */ public function get_javascript_l10n() { global $post; // `include` (not `include_once`): include_once returns true (1) on subsequent // calls, which would corrupt $i18n into an integer. The file is just a // `return array(...)`; re-including it is cheap and correct. $i18n = include trailingslashit( AFFILIZZ_DIRECTORY ) . 'includes/i18n.php'; $current_user_id = get_current_user_id(); return apply_filters( 'affilizz_publications_javascript_l10n', array( 'language' => $i18n, 'ajax_url' => admin_url( 'admin-ajax.php' ), 'debug_enabled' => ( get_option( 'affilizz_javascript_debug_mode' ) === '1' ), 'analytics_enabled' => ( get_option( 'affilizz_javascript_analytics' ) === '1' ), 'api' => array( 'url_pattern' => trim( self::get_api_url_pattern(), '/' ), ), 'plugin' => array( 'url' => esc_url( AFFILIZZ_URL ), ), 'configuration' => array( 'media' => ( ! empty( get_option( 'affilizz_media' ) ) ? get_option( 'affilizz_media' ) : false ), ), 'constants' => array( 'plugin_url' => esc_url( AFFILIZZ_URL ), 'rendering_script_url' => esc_url( ( \Affilizz\Util\Assets::get_instance() )->get_diverted_js_file_url() ), 'urls' => array( 'create' => esc_url( AFFILIZZ_CREATE_PUBLICATION_URL ), 'edit' => esc_url( AFFILIZZ_EDIT_PUBLICATION_URL ), ), ), 'variables' => array( 'current_post' => ( ! empty( $post ) && ! empty( $post->ID ) ? $post->ID // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only admin context used only to localize the current edited post ID. : ( ! empty( $_GET['post'] ) ? sanitize_text_field( wp_unslash( $_GET['post'] ) ) : 0 ) ), 'current_user' => $current_user_id ? $current_user_id : 0, 'current_user_is_admin' => current_user_can( 'manage_options' ), ), ) ); } /** * Force the HTTP request timeout for Affilizz related requests to be the one configured. * @param $timeout_value The current timeout value. * @return float The new timeout value. */ public function force_http_request_timeout( $timeout_value, $url ) { if ( strpos( strtolower( $url ), 'affilizz' ) !== false ) { return self::get_api_http_timeout(); } return $timeout_value; } } Core::get_instance();