qsdklsqkdmqskdmlqskd azoepqikdomlqskdjmlqs qpfklqjsfmklqsjdmqlsjdsqd PKE\vj";";components/lib/WPHttp.phpnu[=' ) ) { require_once ABSPATH . WPINC . '/class-wp-http.php'; } else { require_once ABSPATH . WPINC . '/class-http.php'; } /** * Some 3rd-party APIs require data to be sent in the request body for * GET requests (eg. SendinBlue). This is not currently possible using the WP * HTTP API. I've submitted a patch to WP Core for this. Until its merged, we * have to extend the WP_HTTP class and override the method in question. * * @see https://core.trac.wordpress.org/ticket/39043 * * @private */ class ET_Core_LIB_WPHttp extends WP_Http { /** * Send an HTTP request to a URI. * * Please note: The only URI that are supported in the HTTP Transport implementation * are the HTTP and HTTPS protocols. * * @access public * @since 2.7.0 * * @param string $url The request URL. * @param string|array $args { * Optional. Array or string of HTTP request arguments. * * @type string $method Request method. Accepts 'GET', 'POST', 'HEAD', or 'PUT'. * Some transports technically allow others, but should not be * assumed. Default 'GET'. * @type int $timeout How long the connection should stay open in seconds. Default 5. * @type int $redirection Number of allowed redirects. Not supported by all transports * Default 5. * @type string $httpversion Version of the HTTP protocol to use. Accepts '1.0' and '1.1'. * Default '1.0'. * @type string $user-agent User-agent value sent. * Default WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ). * @type bool $reject_unsafe_urls Whether to pass URLs through wp_http_validate_url(). * Default false. * @type bool $blocking Whether the calling code requires the result of the request. * If set to false, the request will be sent to the remote server, * and processing returned to the calling code immediately, the caller * will know if the request succeeded or failed, but will not receive * any response from the remote server. Default true. * @type string|array $headers Array or string of headers to send with the request. * Default empty array. * @type array $cookies List of cookies to send with the request. Default empty array. * @type string|array $body Body to send with the request. Default null. * @type bool $compress Whether to compress the $body when sending the request. * Default false. * @type bool $decompress Whether to decompress a compressed response. If set to false and * compressed content is returned in the response anyway, it will * need to be separately decompressed. Default true. * @type bool $sslverify Whether to verify SSL for the request. Default true. * @type string sslcertificates Absolute path to an SSL certificate .crt file. * Default ABSPATH . WPINC . '/certificates/ca-bundle.crt'. * @type bool $stream Whether to stream to a file. If set to true and no filename was * given, the stream will be output to a new file in the WP temp dir * using a name generated from the basename of the URL. Default false. * @type string $filename Filename of the file to write to when streaming. $stream must be * set to true. Default null. * @type int $limit_response_size Size in bytes to limit the response to. Default null. * @type bool|null $data_format How the `$data` should be sent ('query' or 'body'). Default null. * If null, data will be sent as 'query' for HEAD/GET and as * 'body' for POST/PUT/OPTIONS/PATCH/DELETE. * * } * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. * A WP_Error instance upon error. */ public function request( $url, $args = array() ) { $defaults = array( 'method' => 'GET', /** * Filters the timeout value for an HTTP request. * * @since 2.7.0 * * @param int $timeout_value Time in seconds until a request times out. * Default 5. */ 'timeout' => apply_filters( 'http_request_timeout', 5 ), /** * Filters the number of redirects allowed during an HTTP request. * * @since 2.7.0 * * @param int $redirect_count Number of redirects allowed. Default 5. */ 'redirection' => apply_filters( 'http_request_redirection_count', 5 ), /** * Filters the version of the HTTP protocol used in a request. * * @since 2.7.0 * * @param string $version Version of HTTP used. Accepts '1.0' and '1.1'. * Default '1.0'. */ 'httpversion' => apply_filters( 'http_request_version', '1.0' ), /** * Filters the user agent value sent with an HTTP request. * * @since 2.7.0 * * @param string $user_agent WordPress user agent string. */ 'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) ), /** * Filters whether to pass URLs through wp_http_validate_url() in an HTTP request. * * @since 3.6.0 * * @param bool $pass_url Whether to pass URLs through wp_http_validate_url(). * Default false. */ 'reject_unsafe_urls' => apply_filters( 'http_request_reject_unsafe_urls', false ), 'blocking' => true, 'headers' => array(), 'cookies' => array(), 'body' => null, 'compress' => false, 'decompress' => true, 'sslverify' => true, 'sslcertificates' => ABSPATH . WPINC . '/certificates/ca-bundle.crt', 'stream' => false, 'filename' => null, 'limit_response_size' => null, 'data_format' => null, ); // Pre-parse for the HEAD checks. $args = wp_parse_args( $args ); // By default, Head requests do not cause redirections. if ( isset( $args['method'] ) && 'HEAD' === $args['method'] ) { $defaults['redirection'] = 0; } $request_args = wp_parse_args( $args, $defaults ); /** * Filters the arguments used in an HTTP request. * * @since 2.7.0 * * @param array $request_args An array of HTTP request arguments. * @param string $url The request URL. */ $request_args = apply_filters( 'http_request_args', $request_args, $url ); // The transports decrement this, store a copy of the original value for loop purposes. if ( ! isset( $request_args['_redirection'] ) ) { $request_args['_redirection'] = $request_args['redirection']; } /** * Filters whether to preempt an HTTP request's return value. * * Returning a non-false value from the filter will short-circuit the HTTP request and return * early with that value. A filter should return either: * * - An array containing 'headers', 'body', 'response', 'cookies', and 'filename' elements * - A WP_Error instance * - boolean false (to avoid short-circuiting the response) * * Returning any other value may result in unexpected behaviour. * * @since 2.9.0 * * @param false|array|WP_Error $preempt Whether to preempt an HTTP request's return value. Default false. * @param array $request_args HTTP request arguments. * @param string $url The request URL. */ $pre = apply_filters( 'pre_http_request', false, $request_args, $url ); if ( false !== $pre ) { return $pre; } if ( function_exists( 'wp_kses_bad_protocol' ) ) { if ( $request_args['reject_unsafe_urls'] ) { $url = wp_http_validate_url( $url ); } if ( $url ) { $url = wp_kses_bad_protocol( $url, array( 'http', 'https', 'ssl' ) ); } } $arrURL = @parse_url( $url ); if ( empty( $url ) || empty( $arrURL['scheme'] ) ) { return new WP_Error( 'http_request_failed', esc_html__( 'A valid URL was not provided.' ) ); } if ( $this->block_request( $url ) ) { return new WP_Error( 'http_request_failed', esc_html__( 'User has blocked requests through HTTP.' ) ); } // If we are streaming to a file but no filename was given drop it in the WP temp dir // and pick its name using the basename of the $url if ( $request_args['stream'] ) { if ( empty( $request_args['filename'] ) ) { $request_args['filename'] = get_temp_dir() . basename( $url ); } // Force some settings if we are streaming to a file and check for existence and perms of destination directory $request_args['blocking'] = true; if ( ! wp_is_writable( dirname( $request_args['filename'] ) ) ) { return new WP_Error( 'http_request_failed', esc_html__( 'Destination directory for file streaming does not exist or is not writable.' ) ); } } if ( is_null( $request_args['headers'] ) ) { $request_args['headers'] = array(); } // WP allows passing in headers as a string, weirdly. if ( ! is_array( $request_args['headers'] ) ) { $processedHeaders = WP_Http::processHeaders( $request_args['headers'] ); $request_args['headers'] = $processedHeaders['headers']; } // Setup arguments $headers = $request_args['headers']; $data = $request_args['body']; $type = $request_args['method']; $options = array( 'timeout' => $request_args['timeout'], 'useragent' => $request_args['user-agent'], 'blocking' => $request_args['blocking'], 'hooks' => new WP_HTTP_Requests_Hooks( $url, $request_args ), ); // Ensure redirects follow browser behaviour. $options['hooks']->register( 'requests.before_redirect', array( get_class(), 'browser_redirect_compatibility' ) ); if ( $request_args['stream'] ) { $options['filename'] = $request_args['filename']; } if ( empty( $request_args['redirection'] ) ) { $options['follow_redirects'] = false; } else { $options['redirects'] = $request_args['redirection']; } // Use byte limit, if we can if ( isset( $request_args['limit_response_size'] ) ) { $options['max_bytes'] = $request_args['limit_response_size']; } // If we've got cookies, use and convert them to Requests_Cookie. if ( ! empty( $request_args['cookies'] ) ) { $options['cookies'] = WP_Http::normalize_cookies( $request_args['cookies'] ); } // SSL certificate handling if ( ! $request_args['sslverify'] ) { $options['verify'] = false; $options['verifyname'] = false; } else { $options['verify'] = $request_args['sslcertificates']; } if ( null !== $request_args['data_format'] ) { $options['data_format'] = $request_args['data_format']; } elseif ( 'HEAD' !== $type && 'GET' !== $type ) { // All non-GET/HEAD requests should put the arguments in the form body. $options['data_format'] = 'body'; } /** * Filters whether SSL should be verified for non-local requests. * * @since 2.8.0 * * @param bool $ssl_verify Whether to verify the SSL connection. Default true. */ $options['verify'] = apply_filters( 'https_ssl_verify', $options['verify'] ); // Check for proxies. $proxy = new WP_HTTP_Proxy(); if ( $proxy->is_enabled() && $proxy->send_through_proxy( $url ) ) { $options['proxy'] = new Requests_Proxy_HTTP( $proxy->host() . ':' . $proxy->port() ); if ( $proxy->use_authentication() ) { $options['proxy']->use_authentication = true; $options['proxy']->user = $proxy->username(); $options['proxy']->pass = $proxy->password(); } } // Avoid issues where mbstring.func_overload is enabled mbstring_binary_safe_encoding(); try { // Since WP 6.2, the 'Requests_Exception' class is deprecated in favor of the // 'WpOrg\Requests\Requests' class due to Requests library upgraded to 2.0.5. if ( class_exists( 'WpOrg\Requests\Requests' ) ) { $requests_response = WpOrg\Requests\Requests::request( $url, $headers, $data, $type, $options ); } else { $requests_response = Requests::request( $url, $headers, $data, $type, $options ); } // Convert the response into an array $http_response = new WP_HTTP_Requests_Response( $requests_response, $request_args['filename'] ); $response = $http_response->to_array(); // Add the original object to the array. $response['http_response'] = $http_response; } catch ( Exception $e ) { // Since there is no change on the error details and the method to get the error // message, we can use `Exception` to cover both of `WpOrg\Requests\Exception` and // `Requests_Exception` classes. $response = new WP_Error( 'http_request_failed', $e->getMessage() ); } reset_mbstring_encoding(); /** * Fires after an HTTP API response is received and before the response is returned. * * @since 2.8.0 * * @param array|WP_Error $response HTTP response or WP_Error object. * @param string $context Context under which the hook is fired. * @param string $class HTTP transport used. * @param array $args HTTP request arguments. * @param string $url The request URL. */ do_action( 'http_api_debug', $response, 'response', 'Requests', $request_args, $url ); if ( is_wp_error( $response ) ) { return $response; } if ( ! $request_args['blocking'] ) { return array( 'headers' => array(), 'body' => '', 'response' => array( 'code' => false, 'message' => false, ), 'cookies' => array(), 'http_response' => null, ); } /** * Filters the HTTP API response immediately before the response is returned. * * @since 2.9.0 * * @param array $response HTTP response. * @param array $request_args HTTP request arguments. * @param string $url The request URL. */ return apply_filters( 'http_response', $response, $request_args, $url ); } } PKE\ Wu6u6components/lib/OAuth.phpnu[ $value ) { if ( is_array( $value ) ) { // When two or more parameters share the same name, they are sorted by their value // Ref: Spec: 9.1.1 (1) // June 12th, 2010 - changed to sort because of issue 164 by hidetaka sort( $value, SORT_STRING ); foreach ( $value as $duplicate_value ) { $pairs[] = "{$parameter}={$duplicate_value}"; } } else { $pairs[] = "{$parameter}={$value}"; } } // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) // Each name-value pair is separated by an '&' character (ASCII code 38) return implode( '&', $pairs ); } public static function parse_parameters( $input = '' ) { if ( '' === $input ) { return array(); } $pairs = explode( '&', $input ); $parsed_parameters = array(); foreach ( $pairs as $pair ) { $split = explode( '=', $pair, 2 ); $parameter = ET_Core_LIB_OAuthUtil::urldecode_rfc3986( $split[0] ); $value = isset( $split[1] ) ? ET_Core_LIB_OAuthUtil::urldecode_rfc3986( $split[1] ) : ''; if ( isset( $parsed_parameters[ $parameter ] ) ) { // We have already received parameter(s) with this name, so add to the list // of parameters with this name if ( is_scalar( $parsed_parameters[ $parameter ] ) ) { // This is the first duplicate, so transform scalar (string) into an array // so we can add the duplicates $parsed_parameters[ $parameter ] = array( $parsed_parameters[ $parameter ] ); } $parsed_parameters[ $parameter ][] = $value; } else { $parsed_parameters[ $parameter ] = $value; } } return $parsed_parameters; } public static function urldecode_rfc3986( $string ) { return rawurldecode( $string ); } public static function urlencode_rfc3986( $input ) { $output = ''; if ( is_array( $input ) ) { $output = array_map( array( 'ET_Core_LIB_OAuthUtil', 'urlencode_rfc3986' ), $input ); } else if ( is_scalar( $input ) ) { $output = rawurlencode( utf8_encode( $input ) ); } return $output; } } /** * A base class for implementing a Signature Method * See section 9 ("Signing Requests") in the spec */ abstract class ET_Core_LIB_OAuthSignatureMethod { /** * Build the signature * NOTE: The output of this function MUST NOT be urlencoded. The encoding is handled in * {@link ET_Core_OAuth_Request} when the final request is serialized. * * @param ET_Core_LIB_OAuthRequest $request * @param ET_Core_LIB_OAuthConsumer $consumer * @param ET_Core_LIB_OAuthToken|null $token * * @return string */ abstract public function build_signature( $request, $consumer, $token = null ); /** * Verifies that a given signature is correct * * @param ET_Core_LIB_OAuthRequest $request * @param ET_Core_LIB_OAuthConsumer $consumer * @param ET_Core_LIB_OAuthToken $token * @param string $signature * * @return bool */ public function check_signature( $request, $consumer, $token, $signature ) { $built = $this->build_signature( $request, $consumer, $token ); // Check for zero length, although its unlikely here if ( empty( $built ) || empty( $signature ) ) { return false; } if ( strlen( $built ) !== strlen( $signature ) ) { return false; } // Avoid a timing leak with a (hopefully) time insensitive compare $result = 0; for ( $i = 0; $i < strlen( $signature ); $i ++ ) { $result |= ord( $built[ $i ] ) ^ ord( $signature[ $i ] ); } return 0 === $result; } /** * Returns the name of this Signature Method (ie HMAC-SHA1) * * @return string */ abstract public function get_name(); } /** * The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] where * the Signature Base String is the text and the key is the concatenated values of the Consumer Secret and * Token Secret (each encoded per Parameter Encoding first), separated by an '&' character (ASCII code 38) * even if empty. As per Chapter 9.2 of the HMAC-SHA1 spec. */ class ET_Core_LIB_OAuthHMACSHA1 extends ET_Core_LIB_OAuthSignatureMethod { /** * @inheritDoc */ public function build_signature( $request, $consumer, $token = null ) { $base_string = $request->get_signature_base_string(); $token = $token ? $token->secret : ''; $request->base_string = $base_string; $key_parts = array( $consumer->secret, $token ); $key = implode( '&', $key_parts ); return base64_encode( hash_hmac( 'sha1', $base_string, $key, true ) ); } /** * @inheritDoc */ public function get_name() { return 'HMAC-SHA1'; } } class ET_Core_LIB_OAuthConsumer { public $callback_url; public $id; public $key; public $secret; public function __construct( $id, $secret, $callback_url = '' ) { $this->id = $this->key = $id; $this->secret = $secret; $this->callback_url = $callback_url; } function __toString() { $name = get_class( $this ); $key = 'ET_Core_LIB_OAuthConsumer' === $name ? 'key' : 'id'; return "{$name}[{$key}={$this->key}, secret={$this->secret}]"; } } class ET_Core_LIB_OAuthToken { public $key; public $secret; public $refresh_token; /** * @param string $key The OAuth Token * @param string $secret The OAuth Token Secret */ public function __construct( $key, $secret ) { $this->key = $key; $this->secret = $secret; } /** * Generates the basic string serialization of a token that a server * would respond to 'request_token' and 'access_token' calls with * * @return string */ public function __toString() { return sprintf( "oauth_token=%s&oauth_token_secret=%s", ET_Core_LIB_OAuthUtil::urlencode_rfc3986( $this->key ), ET_Core_LIB_OAuthUtil::urlencode_rfc3986( $this->secret ) ); } } class ET_Core_LIB_OAuthRequest extends ET_Core_LIB_OAuthBase { protected $parameters; protected $http_method; protected $http_url; public static $version = '1.0'; public $base_string; /** * ET_Core_OAuth_Request Constructor * * @param string $http_method * @param string $http_url * @param array|null $parameters */ public function __construct( $http_method, $http_url, $parameters = array() ) { $this->parameters = $parameters; $this->http_method = $http_method; $this->http_url = $http_url; } /** * pretty much a helper function to set up the request * * @param ET_Core_LIB_OAuthConsumer $consumer * @param ET_Core_LIB_OAuthToken $token * @param string $http_method * @param string $http_url * @param array $parameters * * @return ET_Core_LIB_OAuthRequest */ public static function from_consumer_and_token( $consumer, $token, $http_method, $http_url, $parameters = array() ) { $defaults = array( "oauth_version" => ET_Core_LIB_OAuthRequest::$version, "oauth_nonce" => ET_Core_LIB_OAuthRequest::generate_nonce(), "oauth_timestamp" => time(), "oauth_consumer_key" => $consumer->key ); if ( $token ) { $defaults['oauth_token'] = $token->key; } $parameters = wp_parse_args( $parameters, $defaults ); return new ET_Core_LIB_OAuthRequest( $http_method, $http_url, $parameters ); } /** * Returns the HTTP Method in uppercase * * @return string */ public function get_normalized_http_method() { return strtoupper( $this->http_method ); } /** * parses the url and rebuilds it to be * scheme://host/path * * @return string */ public function get_normalized_http_url() { $parts = parse_url( $this->http_url ); $scheme = $parts['scheme']; $host = strtolower( $parts['host'] ); $path = $parts['path']; return "{$scheme}://{$host}{$path}"; } /** * @param $name * * @return string|null */ public function get_parameter( $name ) { return isset( $this->parameters[ $name ] ) ? $this->parameters[ $name ] : null; } /** * @return array */ public function get_parameters() { return $this->parameters; } /** * The request parameters, sorted and concatenated into a normalized string. * * @return string */ public function get_signable_parameters() { // Grab a copy of all parameters $params = $this->parameters; // Remove oauth_signature if present // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") if ( isset( $params['oauth_signature'] ) ) { unset( $params['oauth_signature'] ); } return ET_Core_LIB_OAuthUtil::build_http_query( $params ); } /** * Returns the base string of this request * * The base string defined as the method, the url, and the parameters (normalized), * each urlencoded and then concatenated with '&'. * * @return string */ public function get_signature_base_string() { $parts = array( $this->get_normalized_http_method(), $this->get_normalized_http_url(), $this->get_signable_parameters() ); $parts = ET_Core_LIB_OAuthUtil::urlencode_rfc3986( $parts ); return implode( '&', $parts ); } /** * @param $name */ public function remove_parameter( $name ) { unset( $this->parameters[ $name ] ); } /** * @param string $name * @param string $value */ public function set_parameter( $name, $value ) { $this->parameters[ $name ] = $value; } /** * Builds the data one would send in a POST request * @param bool $need_json indicates the query data format ( http query string or json string ) * * @return string */ public function to_post_data( $need_json = false ) { return ET_Core_LIB_OAuthUtil::build_http_query( $this->parameters, $need_json ); } /** * Builds a url usable for a GET request * * @return string */ public function to_url() { $postData = $this->to_post_data(); $out = $this->get_normalized_http_url(); if ( $postData ) { $out .= '?' . $postData; } return $out; } /** * Builds the HTTP Authorization Header * * @return string */ public function to_header() { $out = ''; foreach ( $this->parameters as $parameter => $value ) { if ( 0 !== strpos( 'oauth', $parameter ) ) { continue; } if ( is_array( $value ) ) { self::write_log( 'Arrays not supported in headers!', 'ERROR' ); continue; } $out .= ( '' === $out ) ? 'OAuth ' : ', '; $out .= ET_Core_LIB_OAuthUtil::urlencode_rfc3986( $parameter ); $out .= '="' . ET_Core_LIB_OAuthUtil::urlencode_rfc3986( $value ) . '"'; } return $out; } /** * @return string */ public function __toString() { return $this->to_url(); } /** * @param ET_Core_LIB_OAuthSignatureMethod $signature_method * @param ET_Core_LIB_OAuthConsumer $consumer * @param ET_Core_LIB_OAuthToken $token */ public function sign_request( $signature_method, $consumer, $token = null ) { $this->set_parameter( 'oauth_signature_method', $signature_method->get_name() ); $signature = $this->build_signature( $signature_method, $consumer, $token ); $this->set_parameter( 'oauth_signature', $signature ); } /** * @param ET_Core_LIB_OAuthSignatureMethod $signatureMethod * @param ET_Core_LIB_OAuthConsumer $consumer * @param ET_Core_LIB_OAuthToken $token * * @return string */ public function build_signature( $signatureMethod, $consumer, $token = null ) { return $signatureMethod->build_signature( $this, $consumer, $token ); } /** * @return string */ public static function generate_nonce() { return md5( microtime() . mt_rand() ); } } PKE\N components/lib/BluehostCache.phpnu[purged = array(); $this->trigger = null; $this->cache_level = get_option( 'endurance_cache_level', 2 ); $this->cache_dir = WP_CONTENT_DIR . '/endurance-page-cache'; $this->cache_exempt = array( 'wp-admin', '.', 'checkout', 'cart', 'wp-json', '%', '=', '@', '&', ':', ';', ); } public static function get_instance() { if ( null === self::$_instance ) { self::$_instance = new self; } return self::$_instance; } public function clear( $post_id = '' ) { if ( '' !== $post_id && method_exists( $this, 'purge_single' ) ) { $this->purge_single( get_the_permalink( $post_id ) ); } else if ( '' === $post_id && method_exists( $this, 'purge_all' ) ) { $this->purge_all(); } } } PKE\K\components/lib/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\:[[*components/lib/SilentThemeUpgraderSkin.phpnu[instance = et_core_cache_get( $context, 'et_core_portability' ); self::$_ = ET_Core_Data_Utils::instance(); if ( $this->instance && $this->instance->view ) { if ( et_core_is_fb_enabled() ) { $this->assets(); } else { add_action( 'admin_footer', array( $this, 'modal' ) ); add_action( 'customize_controls_print_footer_scripts', array( $this, 'modal' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'assets' ), 5 ); } } } public static function doing_import() { return self::$_doing_import; } /** * Import a previously exported layout. * * @since 3.10 Return the result of the import instead of dieing. * @since 2.7.0 * * @param string $file_context Accepts 'upload', 'sideload'. Default 'upload'. * * @return bool|array */ public function import( $file_context = 'upload' ) { global $shortname; $this->prevent_failure(); self::$_doing_import = true; $timestamp = $this->get_timestamp(); $filesystem = $this->set_filesystem(); $temp_file_id = sanitize_file_name( $timestamp ); $temp_file = $this->has_temp_file( $temp_file_id, 'et_core_import' ); // phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce verification is handled earlier. $include_global_presets = isset( $_POST['include_global_presets'] ) ? wp_validate_boolean( sanitize_text_field( $_POST['include_global_presets'] ) ) : false; $return_json = isset( $_POST['et_cloud_return_json'] ) ? wp_validate_boolean( sanitize_text_field( $_POST['et_cloud_return_json'] ) ) : false; $temp_presets = isset( $_POST['et_cloud_use_temp_presets'] ) ? wp_validate_boolean( sanitize_text_field( $_POST['et_cloud_use_temp_presets'] ) ) : false; $is_update_preset_id = isset( $_POST['onboarding'] ) ? wp_validate_boolean( sanitize_text_field( $_POST['onboarding'] ) ) : false; $preset_prefix = isset( $_POST['preset_prefix'] ) ? sanitize_text_field( $_POST['preset_prefix'] ) : ''; // phpcs:enable WordPress.Security.NonceVerification.Missing $global_presets = ''; if ( $temp_file ) { $import = json_decode( $filesystem->get_contents( $temp_file ), true ); } else { if ( ! isset( $_FILES['file']['name'] ) || ! et_()->ends_with( sanitize_file_name( $_FILES['file']['name'] ), '.json' ) ) { return array( 'message' => 'invalideFile' ); } if ( ! in_array( $file_context, array( 'upload', 'sideload' ) ) ) { $file_context = 'upload'; } $handle_file = "wp_handle_{$file_context}"; $upload = $handle_file( $_FILES['file'], array( 'test_size' => false, 'test_type' => false, 'test_form' => false, ) ); /** * Fires before an uploaded Portability JSON file is processed. * * @since 3.0.99 * * @param string $file The absolute path to the uploaded JSON file's temporary location. */ do_action( 'et_core_portability_import_file', $upload['file'] ); $temp_file = $this->temp_file( $temp_file_id, 'et_core_import', $upload['file'] ); $file_content = preg_replace( '/\x{FEFF}/u', '', $filesystem->get_contents( $temp_file ) ); // Replace BOM with empty string. $import = json_decode( $file_content, true ); $import = $this->validate( $import ); if ( $return_json ) { return array( 'jsonFromFile' => $import ); } // Check if Import contains Google Api Settings. if ( isset( $import['data']['et_google_api_settings'] ) && ( 'epanel' === $this->instance->context || 'epanel_temp' === $this->instance->context ) ) { $et_google_api_settings = $import['data']['et_google_api_settings']; } if ( ! isset( $import['context'] ) || ( isset( $import['context'] ) && $import['context'] !== $this->instance->context ) ) { $this->delete_temp_files( 'et_core_import', [ $temp_file_id => $temp_file ] ); return array( 'message' => 'importContextFail' ); } $import['data'] = $this->apply_query( $import['data'], 'set' ); $filesystem->put_contents( $upload['file'], wp_json_encode( (array) $import ) ); } // Upload images and replace current urls. if ( isset( $import['images'] ) ) { $images = $this->maybe_paginate_images( (array) $import['images'], 'upload_images', $timestamp ); $import['data'] = $this->replace_images_urls( $images, $import['data'] ); } if ( ! empty( $import['global_colors'] ) ) { $import['data'] = $this->_maybe_inject_gcid( $import['data'], $import['global_colors'] ); } $data = $import['data']; $success = array( 'timestamp' => $timestamp ); $this->delete_temp_files( 'et_core_import', [ $temp_file_id => $temp_file ] ); if ( 'options' === $this->instance->type ) { // Reset all data besides excluded data. $current_data = $this->apply_query( get_option( $this->instance->target, array() ), 'unset' ); if ( isset( $data['wp_custom_css'] ) && function_exists( 'wp_update_custom_css_post' ) ) { wp_update_custom_css_post( $data['wp_custom_css'] ); if ( 'yes' === get_theme_mod( 'et_pb_css_synced', 'no' ) ) { // If synced, clear the legacy custom css value to avoid unwanted merging of old and new css. $data[ "{$shortname}_custom_css" ] = ''; } } // Import Google API settings. if ( isset( $et_google_api_settings ) ) { // Get exising Google API key, sine it is not added to export. $et_previous_google_api_settings = get_option( 'et_google_api_settings' ); $et_previous_google_api_key = isset( $et_previous_google_api_settings['api_key'] ) ? $et_previous_google_api_settings['api_key'] : ''; $et_google_api_settings['api_key'] = $et_previous_google_api_key; update_option( 'et_google_api_settings', $et_google_api_settings ); } // Merge remaining current data with new data and update options. update_option( $this->instance->target, array_merge( $current_data, $data ) ); set_theme_mod( 'et_pb_css_synced', 'no' ); } // Pass the post content and let js save the post. if ( 'post' === $this->instance->type ) { $success['postContent'] = reset( $data ); // In some cases we receive the post array instaed of shortcode string. Handle this case. $shortcode_string = is_array( $success['postContent'] ) && ! empty( $success['postContent']['post_content'] ) ? $success['postContent']['post_content'] : $success['postContent']; if ( ! empty( $import['presets'] ) ) { $preset_rewrite_map = []; if ( $include_global_presets && ! $is_update_preset_id ) { $preset_rewrite_map = $this->prepare_to_import_layout_presets( $import['presets'] ); $global_presets = $import['presets']; } $shortcode_object = et_fb_process_shortcode( $shortcode_string ); if ( $is_update_preset_id ) { $global_presets = $import['presets']; $vb_presets_lookup = $this->_get_importing_presets_id_name_pairs( $global_presets ); $this->_update_shortcode_with_onboarding_preset( $shortcode_object, $vb_presets_lookup ); } else { $this->rewrite_module_preset_ids( $shortcode_object, $import['presets'], $preset_rewrite_map ); } $shortcode_string = et_fb_process_to_shortcode( $shortcode_object, array(), '', false ); } do_shortcode( $shortcode_string ); $success['postContent'] = $shortcode_string; $success['migrations'] = ET_Builder_Module_Settings_Migration::$migrated; $success['presets'] = isset( $import['presets'] ) && is_array( $import['presets'] ) ? $import['presets'] : (object) array(); } if ( 'post_type' === $this->instance->type ) { $preset_rewrite_map = array(); if ( ! empty( $import['presets'] ) && $include_global_presets ) { $preset_rewrite_map = $this->prepare_to_import_layout_presets( $import['presets'] ); $global_presets = $import['presets']; } foreach ( $data as &$post ) { $shortcode_object = et_fb_process_shortcode( $post['post_content'] ); if ( ! empty( $import['presets'] ) ) { if ( $include_global_presets ) { $this->rewrite_module_preset_ids( $shortcode_object, $import['presets'], $preset_rewrite_map ); } else { $this->_apply_global_presets( $shortcode_object, $import['presets'] ); } } $post_content = et_fb_process_to_shortcode( $shortcode_object, array(), '', false ); // Add slashes for post content to avoid unwanted unslashing (by wp_unslash) while post is inserting. $post['post_content'] = wp_slash( $post_content ); // Upload thumbnail image if exist. if ( ! empty( $post['post_meta'] ) && ! empty( $post['post_meta']['_thumbnail_id'] ) ) { $post_thumbnail_origin_id = (int) $post['post_meta']['_thumbnail_id'][0]; if ( ! empty( $import['thumbnails'] ) && ! empty( $import['thumbnails'][ $post_thumbnail_origin_id ] ) ) { $post_thumbnail_new = $this->upload_images( $import['thumbnails'][ $post_thumbnail_origin_id ] ); $new_thumbnail_data = reset( $post_thumbnail_new ); // New thumbnail image was uploaded and it should be updated. if ( isset( $new_thumbnail_data['replacement_id'] ) ) { $new_thumbnail_id = $new_thumbnail_data['replacement_id']; $post['thumbnail'] = $new_thumbnail_id; if ( ! function_exists( 'wp_crop_image' ) ) { include ABSPATH . 'wp-admin/includes/image.php'; } $thumbnail_path = get_attached_file( $new_thumbnail_id ); // Generate all the image sizes and update thumbnail metadata. $new_metadata = wp_generate_attachment_metadata( $new_thumbnail_id, $thumbnail_path ); wp_update_attachment_metadata( $new_thumbnail_id, $new_metadata ); } } } } $imported_posts = $this->import_posts( $data ); if ( false === $imported_posts ) { /** * Filters the error message when {@see ET_Core_Portability::import()} fails. * * @since 3.0.99 * * @param mixed $error_message Default is `null`. */ if ( $error_message = apply_filters( 'et_core_portability_import_error_message', false ) ) { $error_message = array( 'message' => $error_message ); } return $error_message; } else { $success['imported_posts'] = $imported_posts; } } if ( ! empty( $global_presets ) ) { if ( ! $this->import_global_presets( $global_presets, $temp_presets, true, $preset_prefix, true ) ) { if ( $error_message = apply_filters( 'et_core_portability_import_error_message', false ) ) { $error_message = array( 'message' => $error_message ); } return $error_message; } } if ( ! empty( $import['global_colors'] ) ) { $this->import_global_colors( $import['global_colors'] ); $success['globalColors'] = et_builder_get_all_global_colors( true ); } return $success; } /** * Initiate Export. * * @since 2.7.0 * * @param bool $return * * @return null|array */ public function export( $return = false, $include_used_presets = false ) { $this->prevent_failure(); et_core_nonce_verified_previously(); $timestamp = $this->get_timestamp(); $filesystem = $this->set_filesystem(); $temp_file_id = sanitize_file_name( $timestamp ); $temp_file = $this->has_temp_file( $temp_file_id, 'et_core_export' ); $apply_global_presets = isset( $_POST['apply_global_presets'] ) ? wp_validate_boolean( $_POST['apply_global_presets'] ) : false; $global_presets = ''; $global_colors = ''; $thumbnails = ''; if ( $temp_file ) { $file_data = json_decode( $filesystem->get_contents( $temp_file ) ); $data = (array) $file_data->data; $global_presets = $file_data->presets; $global_colors = $file_data->global_colors; } else { $temp_file = $this->temp_file( $temp_file_id, 'et_core_export' ); if ( 'options' === $this->instance->type ) { $data = get_option( $this->instance->target, array() ); // Export the Customizer "Additional CSS" value as well. if ( function_exists( 'wp_get_custom_css' ) ) { $data[ 'wp_custom_css' ] = wp_get_custom_css(); } } if ( 'post' === $this->instance->type ) { if ( ! ( isset( $_POST['post'] ) || isset( $_POST['content'] ) ) ) { wp_send_json_error(); } $fields_validatation = array( 'ID' => 'intval', // no post_content as the default case for no fields_validation will run it through perms based wp_kses_post, which is exactly what we want. ); $post_data = array( 'post_content' => stripcslashes( $_POST['content'] ), // need to run this through stripcslashes() as thats what wp_kses_post() expects. 'ID' => $_POST['post'], ); $post_data = $this->validate( $post_data, $fields_validatation ); $data = array( $post_data['ID'] => $post_data['post_content'] ); if ( isset( $_POST['global_presets'] ) ) { // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput.InputNotSanitized -- filter_post_data() function does sanitation. $post_global_presets = $this->_filter_post_data( $_POST['global_presets'] ); $global_presets = json_decode( stripslashes( $post_global_presets ) ); } if ( isset( $_POST['global_colors'] ) ) { // phpcs:ignore ET.Sniffs.ValidatedSanitizedInput.InputNotSanitized -- filter_post_data() function does sanitation. $post_global_colors = $this->_filter_post_data( $_POST['global_colors'] ); $global_colors = json_decode( stripslashes( $post_global_colors ) ); } if ( $include_used_presets ) { $used_global_presets = array(); $used_global_colors = array(); $shortcode_object = et_fb_process_shortcode( $post_data['post_content'] ); $used_global_presets = array_merge( $this->get_used_global_presets( $shortcode_object, $used_global_presets ), $used_global_presets ); if ( ! empty( $used_global_presets ) ) { $global_presets = (object) $used_global_presets; } $used_global_colors = $this->_get_used_global_colors( $shortcode_object, $used_global_colors, $global_presets ); if ( ! empty( $used_global_colors ) ) { $global_colors = $this->_get_global_colors_data( $used_global_colors ); } } } if ( 'post_type' === $this->instance->type ) { $data = $this->export_posts_query(); } $data = $this->apply_query( $data, 'set' ); // Export Google API settings. if ( 'epanel' === $this->instance->context || 'epanel_temp' === $this->instance->context ) { $et_google_api_settings = get_option( 'et_google_api_settings', array() ); // Unset google api_key settings to prevent exporting it. if ( isset( $et_google_api_settings['api_key'] ) ) { unset( $et_google_api_settings['api_key'] ); } $data['et_google_api_settings'] = $et_google_api_settings; } if ( 'post_type' === $this->instance->type ) { $used_global_presets = array(); $used_global_colors = array(); $options = array( 'apply_global_presets' => true, ); foreach ( $data as $post ) { $shortcode_object = et_fb_process_shortcode( $post->post_content ); // We have to always process global presets to get the global colors correctly. $global_presets_from_post = $this->get_used_global_presets( $shortcode_object, $used_global_presets ); $used_global_presets = array_merge( $global_presets_from_post, $used_global_presets ); $used_global_colors = $this->_get_used_global_colors( $shortcode_object, $used_global_colors, $global_presets_from_post ); if ( $apply_global_presets ) { $shortcode_object = et_fb_process_to_shortcode( $shortcode_object, $options, '', false ); $post->post_content = $shortcode_object; } } if ( ! empty ( $used_global_presets ) ) { $global_presets = (object) $used_global_presets; } if ( ! empty( $used_global_colors ) ) { $global_colors = $this->_get_global_colors_data( $used_global_colors ); } } // put contents into file, this is temporary, // if images get paginated, this content will be brought back out // of a temp file in paginated request $file_data = array( 'data' => $data, 'presets' => $global_presets, 'global_colors' => $global_colors, ); $filesystem->put_contents( $temp_file, wp_json_encode( $file_data ) ); } $thumbnails = $this->_get_thumbnail_images( $data ); $images = $this->get_data_images( $data ); $data = array( 'context' => $this->instance->context, 'data' => $data, 'presets' => $global_presets, 'global_colors' => $global_colors, 'images' => $this->maybe_paginate_images( $images, 'encode_images', $timestamp ), 'thumbnails' => $thumbnails, ); // Return exported content instead of printing it if ( $return ) { return array_merge( $data, [ 'timestamp' => $timestamp ] ); } $filesystem->put_contents( $temp_file, wp_json_encode( (array) $data ) ); wp_send_json_success( array( 'timestamp' => $timestamp ) ); } /** * Serialize a single layout post in chunks. * * @since 4.0 * * @param integer $id Unique ID to represent this layout serialization. * @param integer $post_id * @param string $content * @param array $theme_builder_meta * @param integer $chunk * * @return array */ public function serialize_layout( $id, $post_id, $content, $theme_builder_meta = array(), $chunk = 0 ) { $this->prevent_failure(); $fields_validatation = array( // No post_content as the default case for no fields_validation will run it through perms based wp_kses_post, which is exactly what we want. 'ID' => 'intval', ); $post_data = array( // Need to run this through stripcslashes() as thats what wp_kses_post() expects. 'post_content' => stripcslashes( $content ), 'ID' => $post_id, ); $shortcode_object = et_fb_process_shortcode( $post_data['post_content'] ); $used_global_colors = $this->get_theme_builder_library_used_global_colors( $shortcode_object ); $post_data = $this->validate( $post_data, $fields_validatation ); $data = array( $post_data['ID'] => $post_data['post_content'] ); $data = $this->apply_query( $data, 'set' ); $images = $this->get_data_images( $data ); $images = $this->chunk_images( $images, 'encode_images', $id, $chunk ); // Generate list of used global colors. if ( ! empty( $used_global_colors ) ) { $global_colors = $this->_get_global_colors_data( $used_global_colors ); } $data = array( 'context' => 'et_builder', 'data' => $data, 'images' => $images['images'], 'post_title' => get_post_field( 'post_title', $post_id ), 'post_type' => get_post_type( $post_id ), 'theme_builder' => $theme_builder_meta, 'global_colors' => $global_colors, ); $chunks = $images['chunks']; $ready = $images['ready']; return array( 'ready' => $ready, 'chunks' => $chunks, 'data' => $data, ); } /** * Serialize Theme Builder templates in chunks. * * @since 4.0 * * @param integer $id Unique ID to represent this theme builder serialization process. * @param array $step * @param integer $steps * @param integer $step_index * @param integer $chunk * * @return array|false */ public function serialize_theme_builder( $id, $step, $steps, $step_index = 0, $chunk = 0 ) { if ( $step_index >= $steps ) { return false; } $this->prevent_failure(); $temp_file_id = sanitize_file_name( 'et_theme_builder_' . $id ); $temp_file = $this->has_temp_file( $temp_file_id, 'et_core_export' ); if ( $temp_file ) { $data = json_decode( $this->get_filesystem()->get_contents( $temp_file ), true ); } else { $temp_file = $this->temp_file( $temp_file_id, 'et_core_export' ); $data = array( 'context' => 'et_theme_builder', 'templates' => array(), 'layouts' => array(), 'presets' => array(), 'has_default_template' => false, 'has_global_layouts' => false, ); } $chunks = 1; switch ( $step['type'] ) { case 'template': $header_id = $step['data']['layouts']['header']['id']; $body_id = $step['data']['layouts']['body']['id']; $footer_id = $step['data']['layouts']['footer']['id']; $is_default = $step['data']['default']; if ( 0 !== $header_id && ! current_user_can( 'edit_post', $header_id ) ) { $step['data']['layouts']['header']['id'] = 0; } if ( 0 !== $body_id && ! current_user_can( 'edit_post', $body_id ) ) { $step['data']['layouts']['body']['id'] = 0; } if ( 0 !== $footer_id && ! current_user_can( 'edit_post', $footer_id ) ) { $step['data']['layouts']['footer']['id'] = 0; } if ( $is_default ) { $data['has_default_template'] = true; } $data['templates'][] = $step['data']; break; case 'layout': $post_id = $step['data']['post_id']; $is_global = $step['data']['is_global']; if ( ! current_user_can( 'edit_post', $post_id ) ) { break; } if ( 0 === $chunk && isset( $data['layouts'][ $post_id ] ) ) { // The layout is already exported. break; } if ( $is_global ) { $data['has_global_layouts'] = true; } $step_data = $this->serialize_layout( $id, $post_id, get_post_field( 'post_content', $post_id ), array( 'is_global' => $is_global, ), $chunk ); $step_data['data']['post_meta'] = array_merge( et_()->array_get( $step_data, 'data.post_meta', array() ), et_core_get_post_builder_meta( $post_id ) ); $data['layouts'][ $post_id ] = $step_data['data']; $chunks = $step_data['chunks']; break; case 'presets': $data['presets'] = $step['data']; break; } $ready = ( $step_index + 1 >= $steps ) && ( $chunk + 1 >= $chunks ); if ( ! $ready ) { $this->get_filesystem()->put_contents( $temp_file, wp_json_encode( $data ) ); } else { $this->delete_temp_files( 'et_core_export', array( $temp_file_id => $temp_file ) ); } return array( 'ready' => $ready, 'chunks' => $chunks, 'data' => $data, ); } /** * Export Theme Builder templates in chunks. * * @since 4.0 * * @param integer $id Unique ID to represent this theme builder export process. * @param array $step * @param integer $steps * @param integer $step_index * @param integer $chunk * * @return array|false */ public function export_theme_builder( $id, $step, $steps, $step_index = 0, $chunk = 0 ) { $result = $this->serialize_theme_builder( $id, $step, $steps, $step_index, $chunk ); if ( false === $result ) { return false; } $temp_file_id = sanitize_file_name( 'et_theme_builder_export_' . $id ); $temp_file = $this->temp_file( $temp_file_id, 'et_core_export' ); if ( $result['ready'] ) { $this->get_filesystem()->put_contents( $temp_file, wp_json_encode( $result[ 'data' ] ) ); } return array_merge( $result, array( 'temp_file' => $temp_file, 'temp_file_id' => $temp_file_id, ) ); } /** * Get whether an array represents a valid Theme Builder export. * * @since 4.0 * * @param array $export * * @return boolean */ public function is_valid_theme_builder_export( $export ) { $valid_context = isset( $export['context'] ) && $export['context'] === $this->instance->context; $has_templates = isset( $export['templates'] ) && is_array( $export['templates'] ); $has_layouts = isset( $export['layouts'] ) && is_array( $export['layouts'] ); return $valid_context && $has_templates && $has_layouts; } /** * Import a single layout in chunks. * * @since 4.0 * * @param string $id Unique ID to represent this layout serialization. * @param array $layout * @param integer $chunk * * @return array|false */ public function import_layout( $id, $layout, $chunk = 0 ) { $post_id = 0; $import = $this->validate( $layout ); if ( false === $import ) { return false; } $import['data'] = $this->apply_query( $import['data'], 'set' ); if ( ! isset( $import['context'] ) || ( isset( $import['context'] ) && 'et_builder' !== $import['context'] ) ) { return false; } $result = $this->chunk_images( self::$_->array_get( $import, 'images', array() ), 'upload_images', $id, $chunk ); if ( $result['ready'] ) { $import['data'] = $this->replace_images_urls( $result['images'], $import['data'] ); $post_type = self::$_->array_get( $import, 'post_type', 'post' ); $post_title = self::$_->array_get( $import, 'post_title', '' ); $post_status = self::$_->array_get( $import, 'post_status', 'publish' ); $post_meta = self::$_->array_get( $import, 'post_meta', array() ); $post_type_object = get_post_type_object( $post_type ); if ( ! $post_type_object || ! current_user_can( $post_type_object->cap->create_posts ) ) { return false; } $content = array_values( $import['data'] ); $content = $content[0]; $args = array( 'post_status' => $post_status, 'post_type' => $post_type, 'post_content' => current_user_can( 'unfiltered_html' ) ? $content : wp_kses_post( $content ), ); if ( ! empty( $post_title ) ) { $args['post_title'] = current_user_can( 'unfiltered_html' ) ? $post_title : wp_kses( $post_title, 'entities' ); } $post_id = et_theme_builder_insert_layout( $args ); if ( is_wp_error( $post_id ) ) { return false; } foreach ( $post_meta as $entry ) { update_post_meta( $post_id, $entry['key'], $entry['value'] ); } // Import Global Colors for each layout. if ( ! empty( $import['global_colors'] ) ) { $this->import_global_colors( $import['global_colors'] ); } } return array( 'ready' => $result['ready'], 'chunks' => $result['chunks'], 'id' => $post_id, ); } /** * Get importing presets ID and name pairs from presets data. * * @since 4.26.1 * * @param array $presets Presets data. */ protected function _get_importing_presets_id_name_pairs( $presets ) { $presets_lookup = []; foreach ( $presets as $module_type => $value ) { $presets_lookup[ $module_type ] = []; foreach ( $value['presets'] as $module_preset_id => $preset ) { $presets_lookup[ $module_type ][ $module_preset_id ] = $preset['name']; } } return $presets_lookup; } /** * Import Theme Builder templates in chunks. * * @since 4.0 * * @param integer $id Unique ID to represent this theme builder import process. * @param array $step * @param integer $steps * @param integer $step_index * @param integer $chunk * * @return array|false */ public function import_theme_builder( $id, $step, $steps, $step_index = 0, $chunk = 0 ) { if ( $step_index >= $steps ) { return false; } $layout_id_map = array(); $chunks = 1; if ( ! isset( $step['type'] ) ) { $step['type'] = ''; } switch ( $step['type'] ) { case 'layout': $presets = et_()->array_get( $step, 'presets', array() ); $presets_rewrite_map = et_()->array_get( $step, 'presets_rewrite_map', array() ); $is_update_preset_id = et_()->array_get( $step, 'is_update_preset_id', false ); $import_presets = et_()->array_get( $step, 'import_presets', false ); $layouts = et_()->array_get( $step['data'], 'data', array() ); if ( $is_update_preset_id ) { $tb_presets_lookup = $this->_get_importing_presets_id_name_pairs( $presets ); } // Apply any presets to the layouts' shortcodes prior to importing them. if ( ! empty( $presets ) && ! empty( $layouts ) ) { foreach ( $layouts as $key => $layout ) { $shortcode_object = et_fb_process_shortcode( $layout ); if ( $import_presets ) { if ( $is_update_preset_id ) { $this->_update_shortcode_with_onboarding_preset( $shortcode_object, $tb_presets_lookup ); } else { $this->rewrite_module_preset_ids( $shortcode_object, $presets, $presets_rewrite_map ); } } else { $this->_apply_global_presets( $shortcode_object, $presets ); } $layouts[ $key ] = et_fb_process_to_shortcode( $shortcode_object, array(), '', false ); } $step['data']['data'] = $layouts; } $result = $this->import_layout( $id, $step['data'], $chunk ); if ( false === $result ) { break; } if ( $result['ready'] ) { if ( ! isset( $layout_id_map[ $step['id'] ] ) ) { $layout_id_map[ $step['id'] ] = array(); } // Since a single layout can be duplicated multiple times if // it's global we have to keep an array of duplicated ids. $layout_id_map[ $step['id'] ][ $step['template_id'] ] = $result['id']; } $chunks = $result['chunks']; break; } $ready = ( $step_index + 1 >= $steps ) && ( $chunk + 1 >= $chunks ); return array( 'ready' => $ready, 'chunks' => $chunks, 'layout_id_map' => $layout_id_map, ); } /** * Download temporary file. * * @since 4.0 * * @param string $filename * @param string $temp_file_id * @param string $temp_file * @return void */ public function download_file( $filename, $temp_file_id, $temp_file ) { $this->prevent_failure(); $filename = sanitize_file_name( $filename ); header( 'Content-Description: File Transfer' ); header( "Content-Disposition: attachment; filename=\"{$filename}.json\"" ); header( 'Content-Type: application/json' ); header( 'Pragma: no-cache' ); if ( file_exists( $temp_file ) ) { echo et_core_esc_previously( $this->get_filesystem()->get_contents( $temp_file ) ); } $this->delete_temp_files( 'et_core_export', array( $temp_file_id => $temp_file ) ); wp_die(); } /** * Download Export Data. * * @since 2.7.0 */ public function download_export() { $this->prevent_failure(); et_core_nonce_verified_previously(); // Retrieve data. $timestamp = isset( $_GET['timestamp'] ) ? sanitize_text_field( $_GET['timestamp'] ) : null; $name = isset( $_GET['name'] ) ? sanitize_text_field( rawurldecode( $_GET['name'] ) ) : $this->instance->name; $filesystem = $this->set_filesystem(); $temp_file = $this->temp_file( sanitize_file_name( $timestamp ), 'et_core_export' ); header( 'Content-Description: File Transfer' ); header( "Content-Disposition: attachment; filename=\"{$name}.json\"" ); header( 'Content-Type: application/json' ); header( 'Pragma: no-cache' ); if ( file_exists( $temp_file ) ) { echo et_core_esc_previously( $filesystem->get_contents( $temp_file ) ); } $this->delete_temp_files( 'et_core_export' ); exit; } protected function to_megabytes( $value ) { $unit = strtoupper( substr( $value, -1 ) ); $amount = intval( substr( $value, 0, -1 ) ); // Known units switch ( $unit ) { case 'G': return $amount << 10; case 'M': return $amount; } if ( is_numeric( $unit ) ) { // Numeric unit is present, assume bytes return intval( $value ) >> 20; } // Unknown unit ... return intval( $value ); }// end to_megabytes() /** * Get selected posts data. * * @since 2.7.0 */ protected function export_posts_query() { et_core_nonce_verified_previously(); $args = array( 'post_type' => $this->instance->target, 'posts_per_page' => -1, 'no_found_rows' => true, ); // Only include selected posts if set and not empty. if ( isset( $_POST['selection'] ) ) { $include = json_decode( stripslashes( $_POST['selection'] ), true ); if ( ! empty( $include ) ) { $include = array_map( 'intval', array_values( $include ) ); $args['post__in'] = $include; } } $get_posts = get_posts( apply_filters( "et_core_portability_export_wp_query_{$this->instance->context}", $args ) ); $taxonomies = get_object_taxonomies( $this->instance->target ); $posts = array(); foreach ( $get_posts as $key => $post ) { unset( $post->post_author, $post->guid ); $posts[$post->ID] = $post; // Include post meta. $post_meta = (array) get_post_meta( $post->ID ); if ( isset( $post_meta['_edit_lock'] ) ) { unset( $post_meta['_edit_lock'], $post_meta['_edit_last'] ); } $posts[$post->ID]->post_meta = $post_meta; // Include terms. $get_terms = (array) wp_get_object_terms( $post->ID, $taxonomies ); $terms = array(); // Order terms to make sure children are after the parents. while ( $term = array_shift( $get_terms ) ) { if ( 0 === $term->parent || isset( $terms[$term->parent] ) ) { $terms[$term->term_id] = $term; } else { // if parent category is also exporting then add the term to the end of the list and process it later // otherwise add a term as usual if ( $this->is_parent_term_included( $get_terms, $term->parent ) ) { $get_terms[] = $term; } else { $terms[$term->term_id] = $term; } } } $posts[$post->ID]->terms = array(); foreach ( $terms as $term ) { $parents_data = array(); if ( $term->parent ) { $parent_slug = isset( $terms[$term->parent] ) ? $terms[$term->parent]->slug : $this->get_parent_slug( $term->parent, $term->taxonomy ); $parents_data = $this->get_all_parents( $term->parent, $term->taxonomy ); } else { $parent_slug = 0; } $posts[$post->ID]->terms[$term->term_id] = array( 'name' => $term->name, 'slug' => $term->slug, 'taxonomy' => $term->taxonomy, 'parent' => $parent_slug, 'all_parents' => $parents_data, 'description' => $term->description ); } } return $posts; } /** * Check whether the $parent_id included into the $terms_list. * * @since 2.7.0 * * @param array $terms_list Array of term objects. * @param int $parent_id . * * @return bool */ protected function is_parent_term_included( $terms_list, $parent_id ) { $is_parent_found = false; foreach ( $terms_list as $term => $term_details ) { if ( $parent_id === $term_details->term_id ) { $is_parent_found = true; } } return $is_parent_found; } /** * Retrieve the term slug. * * @since 2.7.0 * * @param int $parent_id . * @param string $taxonomy . * * @return int|string */ protected function get_parent_slug( $parent_id, $taxonomy ) { $term_data = get_term( $parent_id, $taxonomy ); $slug = '' === $term_data->slug ? 0 : $term_data->slug; return $slug; } /** * Prepare array of all parents so the correct hierarchy can be restored during the import. * * @since 2.7.0 * * @param int $parent_id . * @param string $taxonomy . * * @return array */ protected function get_all_parents( $parent_id, $taxonomy ) { $parents_data_array = array(); $parent = $parent_id; // retrieve data for all parent categories if ( 0 !== $parent ) { while( 0 !== $parent ) { $parent_term_data = get_term( $parent, $taxonomy ); $parents_data_array[$parent_term_data->slug] = array( 'name' => $parent_term_data->name, 'description' => $parent_term_data->description, 'parent' => 0 !== $parent_term_data->parent ? $this->get_parent_slug( $parent_term_data->parent, $taxonomy ) : 0, ); $parent = $parent_term_data->parent; } } //reverse order of items, to simplify the restoring process return array_reverse( $parents_data_array ); } /** * Check if a layout exists in the database already based on both its title and its slug. * * @param string $title * @param string $slug * * @return int $post_id The post id if it exists, zero otherwise. */ protected static function layout_exists( $title, $slug ) { global $wpdb; return (int) $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_name = %s", array( wp_unslash( sanitize_post_field( 'post_title', $title, 0, 'db' ) ), wp_unslash( sanitize_post_field( 'post_name', $slug, 0, 'db' ) ), ) ) ); } /** * Update shortcode with onboarding preset. * * @since 4.26.1 * * @param array $shortcode_object - The shortcode object to be updated. * @param array $presets_lookup - The lookup table for presets. */ protected function _update_shortcode_with_onboarding_preset( &$shortcode_object, $presets_lookup ) { $global_presets_manager = ET_Builder_Global_Presets_Settings::instance(); $module_preset_attribute = ET_Builder_Global_Presets_Settings::MODULE_PRESET_ATTRIBUTE; $global_presets = $global_presets_manager->get_global_presets(); foreach ( $shortcode_object as &$module ) { $module_type = $global_presets_manager->maybe_convert_module_type( $module['type'], $module['attrs'] ); if ( isset( $presets_lookup[ $module_type ] ) ) { $module_preset_id = et_()->array_get( $module, "attrs.{$module_preset_attribute}", 'default' ); if ( 'default' === $module_preset_id ) { continue; } $module_preset_name = et_()->array_get( $presets_lookup, "{$module_type}.{$module_preset_id}", '' ); foreach ( $global_presets->$module_type->presets as $preset_id => $preset ) { if ( $preset->name === $module_preset_name ) { $module['attrs'][ $module_preset_attribute ] = $preset_id; break; } } } if ( isset( $module['content'] ) && is_array( $module['content'] ) ) { $this->_update_shortcode_with_onboarding_preset( $module['content'], $presets_lookup ); } } } /** * Imports Global Presets * * @since 4.0.10 Made public. * * @param array $presets - The Global Presets to be imported. * @param bool $is_temp_presets - Whether the presets are temporary or not. * @param bool $override_defaults - Whether the default presets should be overridden. * @param string $preset_prefix - A prefix to be prepended to preset name of the preset being imported, if override_defaults is true. * @param bool $skip_default - Whether updating the default preset key should be skipped. * * @return boolean */ public function import_global_presets( $presets, $is_temp_presets = false, $override_defaults = false, $preset_prefix = '', $skip_default = false ) { if ( ! is_array( $presets ) ) { return false; } $all_modules = ET_Builder_Element::get_modules(); $module_presets_manager = ET_Builder_Global_Presets_Settings::instance(); $global_presets = $module_presets_manager->get_global_presets(); $temp_presets = $module_presets_manager->get_temp_presets(); $presets_to_import = array(); foreach ( $presets as $module_type => $module_presets ) { $presets_to_import[ $module_type ] = array( 'presets' => array(), ); if ( ! isset( $global_presets->$module_type->presets ) ) { $initial_preset_structure = ET_Builder_Global_Presets_Settings::generate_module_initial_presets_structure( $module_type, $all_modules ); $global_presets->$module_type = $initial_preset_structure; } if ( $override_defaults && ! $skip_default ) { $global_presets->$module_type->default = $module_presets['default']; } $local_presets = $global_presets->$module_type->presets; $local_preset_names = array(); foreach ( $local_presets as $preset_id => $preset ) { // Skip temp presets. if ( ! isset( $temp_preset[ $module_type ]['presets'][ $preset_id ] ) ) { array_push( $local_preset_names, $preset->name ); } } foreach ( $module_presets['presets'] as $preset_id => $preset ) { $name = sanitize_text_field( $preset['name'] ); if ( $override_defaults && $preset_prefix ) { $name = $preset_prefix . ' ' . $name; // No duplicates allowed on override. if ( in_array( $name, $local_preset_names, true ) ) { continue; } } else { if ( in_array( $name, $local_preset_names, true ) ) { $name .= ' ' . esc_html__( 'imported', 'et-core' ); } } $presets_to_import[ $module_type ]['presets'][ $preset_id ] = array( 'name' => $name, 'created' => time() * 1000, 'updated' => time() * 1000, 'version' => $preset['version'], 'settings' => $preset['settings'], ); } } if ( $is_temp_presets ) { et_update_option( ET_Builder_Global_Presets_Settings::GLOBAL_PRESETS_OPTION_TEMP, $presets_to_import ); } // Merge existing Global Presets with imported ones foreach ( $presets_to_import as $module_type => $module_presets ) { foreach ( $module_presets['presets'] as $preset_id => $preset ) { $global_presets->$module_type->presets->$preset_id = (object) array(); $global_presets->$module_type->presets->$preset_id->name = sanitize_text_field( $preset['name'] ); $global_presets->$module_type->presets->$preset_id->created = $preset['created']; $global_presets->$module_type->presets->$preset_id->updated = $preset['updated']; $global_presets->$module_type->presets->$preset_id->version = $preset['version']; $global_presets->$module_type->presets->$preset_id->settings = (object) array(); foreach ( $preset['settings'] as $setting_name => $value ) { $setting_name_sanitized = sanitize_text_field( $setting_name ); $value_sanitized = sanitize_text_field( $value ); $global_presets->$module_type->presets->$preset_id->settings->$setting_name_sanitized = $value_sanitized; } // Inject Global colors into imported presets. $preset_settings = (array) $global_presets->$module_type->presets->$preset_id->settings; $global_presets->$module_type->presets->$preset_id->settings = ET_Builder_Global_Presets_Settings::maybe_set_global_colors( $preset_settings ); } } // Update option for product setting (last attr in args list). et_update_option( ET_Builder_Global_Presets_Settings::GLOBAL_PRESETS_OPTION, $global_presets, false, '', '', true ); if ( ! $is_temp_presets ) { $global_presets_history = ET_Builder_Global_Presets_History::instance(); $global_presets_history->add_global_history_record( $global_presets ); } return true; } /** * Prepare to import non-duplicate presets. * * @since 4.26.0 * * @param array $presets Presets to import. * * @return array */ public function prepare_to_import_non_duplicate_presets( $presets ) { $global_presets_manager = ET_Builder_Global_Presets_Settings::instance(); $existing_presets = $global_presets_manager->get_global_presets(); $existing_names = []; foreach ( $existing_presets as $module_slug => $data ) { foreach ( $data->presets as $preset ) { $existing_names[ $module_slug ][ trim( $preset->name ) ] = true; } } foreach ( $presets as $module_slug => $data ) { foreach ( $data['presets'] as $preset_id => $preset ) { if ( isset( $existing_names[ $module_slug ][ trim( $preset['name'] ) ] ) ) { unset( $presets[ $module_slug ]['presets'][ $preset_id ] ); } } } return $presets; } /** * Import global colors. * * @since 4.9.0 * * @param array $incoming_global_colors Global Colors Array. * * @return void */ public function import_global_colors( $incoming_global_colors ) { $excluded_colors = array( 'gcid-primary-color', 'gcid-secondary-color', 'gcid-heading-color', 'gcid-body-color' ); $global_colors = array(); foreach ( $incoming_global_colors as $incoming_gcolor ) { $key = et_()->sanitize_text_fields( $incoming_gcolor[0] ); // Skip excluded colors. if ( in_array( $key, $excluded_colors, true ) ) { continue; } $global_colors[ $key ] = et_()->sanitize_text_fields( $incoming_gcolor[1] ); } $stored_global_colors = et_builder_get_all_global_colors(); if ( ! empty( $stored_global_colors ) ) { $global_colors = array_merge( $global_colors, $stored_global_colors ); } et_update_option( 'et_global_colors', $global_colors ); } /** * Import post. * * @since 2.7.0 * * @param array $posts Array of data formatted by the portability exporter. * * @return bool */ protected function import_posts( $posts ) { /** * Filters the array of builder layouts to import. Returning an empty value will * short-circuit the import process. * * @since 3.0.99 * * @param array $posts */ $posts = apply_filters( 'et_core_portability_import_posts', $posts ); $imported_posts = array(); if ( empty( $posts ) ) { return false; } foreach ( $posts as $post ) { if ( isset( $post['post_status'] ) && 'auto-draft' === $post['post_status'] ) { continue; } $fields_validatation = array( 'ID' => 'intval', 'post_title' => 'sanitize_text_field', 'post_type' => 'sanitize_text_field', ); if ( ! $post = $this->validate( $post, $fields_validatation ) ) { continue; } $layout_exists = self::layout_exists( $post['post_title'], $post['post_name'] ); if ( $layout_exists && get_post_type( $layout_exists ) === $post['post_type'] ) { // Make sure the post is published. if ( 'publish' !== get_post_status( $layout_exists ) ) { wp_update_post( array( 'ID' => intval( $layout_exists ), 'post_status' => 'publish', ) ); } $imported_posts[] = intval( $layout_exists ); continue; } $post['import_id'] = $post['ID']; unset( $post['ID'] ); $post['post_author'] = (int) get_current_user_id(); // Insert or update post. $post_id = wp_insert_post( $post, true ); if ( ! $post_id || is_wp_error( $post_id ) ) { continue; } $imported_posts[] = $post_id; // Insert and set terms. if ( isset( $post['terms'] ) && is_array( $post['terms'] ) ) { $processed_terms = array(); foreach ( $post['terms'] as $term ) { $fields_validatation = array( 'name' => 'sanitize_text_field', 'slug' => 'sanitize_title', 'taxonomy' => 'sanitize_title', 'parent' => 'sanitize_title', 'description' => 'wp_kses_post', ); if ( ! $term = $this->validate( $term, $fields_validatation ) ) { continue; } if ( empty( $term['parent'] ) ) { $parent = 0; } else { if ( isset( $term['all_parents'] ) && ! empty( $term['all_parents'] ) ) { $this->restore_parent_categories( $term['all_parents'], $term['taxonomy'] ); } $parent = term_exists( $term['parent'], $term['taxonomy'] ); if ( is_array( $parent ) ){ $parent = $parent['term_id']; } } if ( ! $insert = term_exists( $term['slug'], $term['taxonomy'] ) ) { $insert = wp_insert_term( $term['name'], $term['taxonomy'], array( 'slug' => $term['slug'], 'description' => $term['description'], 'parent' => intval( $parent ), ) ); } if ( is_array( $insert ) && ! is_wp_error( $insert ) ) { $processed_terms[$term['taxonomy']][] = $term['slug']; } } // Set post terms. foreach ( $processed_terms as $taxonomy => $ids ) { wp_set_object_terms( $post_id, $ids, $taxonomy ); } } // Insert or update post meta. if ( isset( $post['post_meta'] ) && is_array( $post['post_meta'] ) ) { foreach ( $post['post_meta'] as $meta_key => $meta ) { $meta_key = sanitize_text_field( $meta_key ); if ( count( $meta ) < 2 ) { $meta = wp_kses_post( $meta[0] ); } else { $meta = array_map( 'wp_kses_post', $meta ); } update_post_meta( $post_id, $meta_key, $meta ); } } // Assign new thumbnail if provided. if ( isset( $post['thumbnail'] ) ) { set_post_thumbnail( $post_id, $post['thumbnail'] ); } } return $imported_posts; } /** * Restore the categories hierarchy in library. * * @since 2.7.0 * * @param array $parents_array Array of parent categories data. * @param string $taxonomy */ protected function restore_parent_categories( $parents_array, $taxonomy ) { foreach( $parents_array as $slug => $category_data ) { $current_category = term_exists( $slug, $taxonomy ); if ( ! is_array( $current_category ) ) { $parent_id = 0 !== $category_data['parent'] ? term_exists( $category_data['parent'], $taxonomy ) : 0; wp_insert_term( $category_data['name'], $taxonomy, array( 'slug' => $slug, 'description' => $category_data['description'], 'parent' => is_array( $parent_id ) ? $parent_id['term_id'] : $parent_id, ) ); } else if ( ( ! isset( $current_category['parent'] ) || 0 === $current_category['parent'] ) && 0 !== $category_data['parent'] ) { $parent_id = 0 !== $category_data['parent'] ? term_exists( $category_data['parent'], $taxonomy ) : 0; wp_update_term( $current_category['term_id'], $taxonomy, array( 'parent' => is_array( $parent_id ) ? $parent_id['term_id'] : $parent_id ) ); } } } /** * Generates UUIDs for the presets to avoid collisions. * * @since 4.5.0 * * @param array $global_presets - The Global Presets to be imported * * @return array - The list of module types for which preset ids have been changed */ public function prepare_to_import_layout_presets( &$global_presets ) { $preset_rewrite_map = array(); $initial_preset_id = ET_Builder_Global_Presets_Settings::MODULE_INITIAL_PRESET_ID; foreach ( $global_presets as $component_type => &$component_presets ) { $preset_rewrite_map[ $component_type ] = array(); foreach ( $component_presets['presets'] as $preset_id => $preset ) { $new_id = ET_Core_Data_Utils::uuid_v4(); $component_presets['presets'][ $new_id ] = $preset; $preset_rewrite_map[ $component_type ][ $preset_id ] = $new_id; unset( $component_presets['presets'][ $preset_id ] ); } if ( $component_presets['default'] === $initial_preset_id && ! isset( $preset_rewrite_map[ $component_type ][ $initial_preset_id ] ) ) { $new_id = ET_Core_Data_Utils::uuid_v4(); $component_presets['default'] = $new_id; if ( isset( $component_presets['presets'][ $initial_preset_id ] ) ) { $component_presets['presets'][ $new_id ] = $component_presets['presets'][ $initial_preset_id ]; unset( $component_presets['presets'][ $initial_preset_id ] ); } $preset_rewrite_map[ $component_type ][ $initial_preset_id ] = $new_id; } else { $component_presets['default'] = $preset_rewrite_map[ $component_type ][ $component_presets['default'] ]; } } return $preset_rewrite_map; } /** * Injects the given Global Presets settings into the imported layout * * @since 4.5.0 * * @param array $shortcode_object - The multidimensional array representing a page/module structure * @param array $global_presets - The Global Presets to be imported * @param array $preset_rewrite_map - The list of module types for which preset ids have been changed */ protected function rewrite_module_preset_ids( &$shortcode_object, $global_presets, $preset_rewrite_map ) { $global_presets_manager = ET_Builder_Global_Presets_Settings::instance(); $module_preset_attribute = ET_Builder_Global_Presets_Settings::MODULE_PRESET_ATTRIBUTE; foreach ( $shortcode_object as &$module ) { $module_type = $global_presets_manager->maybe_convert_module_type( $module['type'], $module['attrs'] ); $module_preset_id = et_()->array_get( $module, "attrs.{$module_preset_attribute}", 'default' ); if ( $module_preset_id === 'default' ) { $module['attrs'][ $module_preset_attribute ] = et_()->array_get( $global_presets, "{$module_type}.default", 'default' ); } else { if ( isset( $preset_rewrite_map[ $module_type ][ $module_preset_id ] ) ) { $module['attrs'][ $module_preset_attribute ] = $preset_rewrite_map[ $module_type ][ $module_preset_id ]; } else { $module['attrs'][ $module_preset_attribute ] = et_()->array_get( $global_presets, "{$module_type}.default", 'default' ); } } if ( isset( $module['content'] ) && is_array( $module['content'] ) ) { $this->rewrite_module_preset_ids( $module['content'], $global_presets, $preset_rewrite_map ); } } } /** * Injects global color ids into the imported layout * * @since 4.10.0 * * @param array $data - The multidimensional array representing a import object structure. */ protected function _maybe_inject_gcid( &$data, &$gcolors = null ) { foreach ( $data as $post_id => &$post_data ) { if ( is_array( $post_data ) ) { $shortcode_object = et_fb_process_shortcode( $post_data['post_content'] ); $this->_inject_gcid( $shortcode_object, $gcolors ); $data[ $post_id ]['post_content'] = et_fb_process_to_shortcode( $shortcode_object, array(), '', false ); } else { $shortcode_object = et_fb_process_shortcode( $post_data ); $this->_inject_gcid( $shortcode_object, $gcolors ); $data[ $post_id ] = et_fb_process_to_shortcode( $shortcode_object, array(), '', false ); } } unset( $post_data ); return $data; } /** * Process and inject global color ids into the shortcode * * @since 4.10.0 * * @param array $shortcode_object - The multidimensional array representing a page/module structure. */ protected function _inject_gcid( &$shortcode_object, &$global_colors ) { foreach ( $shortcode_object as &$module ) { // No global colors set for this module. if ( ! empty( $module['attrs']['global_colors_info'] ) && ! empty( $global_colors ) ) { $colors_array = json_decode( $module['attrs']['global_colors_info'], true ); if ( ! empty( $colors_array ) ) { foreach ( $colors_array as $color_id => $attrs_array ) { if ( ! empty( $attrs_array ) ) { // Get settings for this global color. $color = ''; foreach ( $global_colors as $gcid ) { if ( $color_id === $gcid[0] && 'yes' === $gcid[1]['active'] ) { $color = $gcid[1]['color']; } } foreach ( $attrs_array as $attr_name ) { if ( isset( $module['attrs'][ $attr_name ] ) && '' !== $module['attrs'][ $attr_name ] ) { // Match substring (needed for attrs like gradient stops). $module['attrs'][ $attr_name ] = str_replace( $color, $color_id, $module['attrs'][ $attr_name ] ); } } } } } } if ( isset( $module['content'] ) && is_array( $module['content'] ) ) { $this->_inject_gcid( $module['content'], $global_colors ); } } } /** * Injects the given Global Presets settings into the imported layout * * @since 3.26 * * @param array $shortcode_object - The multidimensional array representing a page/module structure * @param array $global_presets - The Global Presets to be applied */ protected function _apply_global_presets( &$shortcode_object, $global_presets ) { $global_presets_manager = ET_Builder_Global_Presets_Settings::instance(); $module_preset_attribute = ET_Builder_Global_Presets_Settings::MODULE_PRESET_ATTRIBUTE; foreach ( $shortcode_object as &$module ) { $module_type = $global_presets_manager->maybe_convert_module_type( $module['type'], $module['attrs'] ); if ( isset( $global_presets[ $module_type ] ) ) { $default_preset_id = et_()->array_get( $global_presets, "{$module_type}.default", null ); $module_preset_id = et_()->array_get( $module, "attrs.{$module_preset_attribute}", $default_preset_id ); if ( 'default' === $module_preset_id ) { $module_preset_id = $default_preset_id; } $preset_settings = array(); if ( isset( $global_presets[ $module_type ]['presets'][ $module_preset_id ] ) ) { $preset_settings = $global_presets[ $module_type ]['presets'][ $module_preset_id ]['settings']; } else { if ( isset( $global_presets[ $module_type ]['presets'][ $default_preset_id ]['settings'] ) ) { $preset_settings = $global_presets[ $module_type ]['presets'][ $default_preset_id ]['settings']; } } $merged_global_colors_info = array(); if ( isset( $module['attrs']['global_colors_info'] ) ) { // Retrive global_colors_info from post meta, which saved as string[][]. $gc_info_prepared = str_replace( array( '[', ']' ), array( '[', ']' ), $module['attrs']['global_colors_info'] ); $used_global_colors = json_decode( $gc_info_prepared, true ); $merged_global_colors_info = $used_global_colors; } // Merge Global Colors from preset. if ( isset( $preset_settings['global_colors_info'] ) ) { $preset_global_colors = json_decode( $preset_settings['global_colors_info'], true ); if ( ! empty( $preset_global_colors ) ) { foreach ( $preset_global_colors as $color_id => $settings_list ) { if ( ! empty( $settings_list ) ) { if ( isset( $used_global_colors[ $color_id ] ) ) { $merged_global_colors_info[ $color_id ] = array_merge( $used_global_colors[ $color_id ], $settings_list ); } else { $merged_global_colors_info[ $color_id ] = $settings_list; } foreach ( $settings_list as $setting_name ) { $preset_settings[ $setting_name ] = $color_id; } } } } } $module['attrs'] = array_merge( $preset_settings, $module['attrs'] ); $module['attrs']['global_colors_info'] = wp_json_encode( $merged_global_colors_info ); } if ( isset( $module['content'] ) && is_array( $module['content'] ) ) { $this->_apply_global_presets( $module['content'], $global_presets ); } } } /** * Restrict data according the argument registered. * * @since 2.7.0 * * @param array $data Array of data the query is applied on. * @param string $method Whether data should be set or reset. Accepts 'set' or 'unset' which is * should be used when treating existing data in the db. * * @return array */ protected function apply_query( $data, $method ) { $operator = ( $method === 'set' ) ? true : false; foreach ( $data as $id => $value ) { if ( ! empty( $this->instance->exclude ) && isset( $this->instance->exclude[$id] ) === $operator ) { unset( $data[$id] ); } if ( ! empty( $this->instance->include ) && isset( $this->instance->include[$id] ) === ! $operator ) { unset( $data[$id] ); } } return $data; } /** * Serialize images in chunks. * * @since 4.0 * * @param array $images * @param string $method Method applied on images. * @param string $id Unique ID to use for temporary files. * @param integer $chunk * * @return array */ protected function chunk_images( $images, $method, $id, $chunk = 0 ) { $images_per_chunk = 5; $chunks = 1; /** * Filters whether or not images in the file being imported should be paginated. * * @since 3.0.99 * * @param bool $paginate_images Default `true`. */ $paginate_images = apply_filters( 'et_core_portability_paginate_images', true ); if ( $paginate_images && count( $images ) > $images_per_chunk ) { $chunks = ceil( count( $images ) / $images_per_chunk ); $slice = $images_per_chunk * $chunk; $images = array_slice( $images, $slice, $images_per_chunk ); $images = $this->$method( $images ); $filesystem = $this->get_filesystem(); $temp_file_id = sanitize_file_name( "images_{$id}" ); $temp_file = $this->temp_file( $temp_file_id, 'et_core_export' ); $temp_images = json_decode( $filesystem->get_contents( $temp_file ), true ); if ( is_array( $temp_images ) ) { $images = array_merge( $temp_images, $images ); } if ( $chunk + 1 < $chunks ) { $filesystem->put_contents( $temp_file, wp_json_encode( (array) $images ) ); } else { $this->delete_temp_files( 'et_core_export', array( $temp_file_id => $temp_file ) ); } } else { $images = $this->$method( $images ); } return array( 'ready' => $chunk + 1 >= $chunks, 'chunks' => $chunks, 'images' => $images, ); } /** * Paginate images processing. * * @since 1.0.0 * * @param $images * @param string $method Method applied on images. * @param int $timestamp Timestamp used to store data upon pagination. * * @return array * @internal param array $data Array of images. */ protected function maybe_paginate_images( $images, $method, $timestamp ) { et_core_nonce_verified_previously(); $page = isset( $_POST['page'] ) ? (int) $_POST['page'] : 1; $result = $this->chunk_images( $images, $method, $timestamp, max( $page - 1, 0 ) ); if ( ! $result['ready'] ) { wp_send_json( array( 'page' => $page, 'total_pages' => $result['chunks'], 'timestamp' => $timestamp, ) ); } return $result['images']; } /** * Get all thumbnail images in the data given. * * @since 4.7.4 * * @param array $data Array of data. * * @return array */ protected function _get_thumbnail_images( $data ) { $thumbnails = array(); foreach ( $data as $post_data ) { // If post has thumbnail. if ( ! empty( $post_data->post_meta ) && ! empty( $post_data->post_meta->_thumbnail_id ) ) { $post_thumbnail = get_the_post_thumbnail_url( $post_data->ID ); // If thumbnail image found in the WP Media library. if ( $post_thumbnail ) { $thumbnail_id = (int) $post_data->post_meta->_thumbnail_id[0]; $thumbnail_image = $this->encode_images( array( $thumbnail_id ) ); $thumbnails[ $thumbnail_id ] = $thumbnail_image; } } } return $thumbnails; } /** * Get all images in the data given. * * @since 2.7.0 * * @param array $data Array of data. * @param bool $force Set whether the value should be added by force. Usually used for image ids. * * @return array */ protected function get_data_images( $data, $force = false ) { if ( empty( $data ) ) { return array(); } $images = array(); $images_src = array(); $basenames = array( 'src', 'image_url', 'background_image', 'image', 'url', 'bg_img_?\d?', ); $suffixes = array( '__hover', '_tablet', '_phone' ); foreach ( $basenames as $basename ) { $images_src[] = $basename; foreach ( $suffixes as $suffix ) { $images_src[] = $basename . $suffix; } } foreach ( $data as $value ) { // If the $value is an object and there is no post_content property, // it's unlikely to contain any image data so we can continue with the next iteration. if ( is_object( $value ) && ! property_exists( $value, 'post_content' ) ) { continue; } if ( is_array( $value ) || is_object( $value ) ) { // If the $value contains the post_content property, set $value to use // this object's property value instead of the entire object. if ( is_object( $value ) && property_exists( $value, 'post_content' ) ) { $value = $value->post_content; } $images = array_merge( $images, $this->get_data_images( (array) $value ) ); continue; } // Extract images from HTML or shortcodes. if ( preg_match_all( '/(' . implode( '|', $images_src ) . ')="(?P\w+[^"]*)"/i', $value, $matches ) ) { foreach ( array_unique( $matches['src'] ) as $key => $src ) { $images = array_merge( $images, $this->get_data_images( array( $key => $src ) ) ); } } // Extract images from shortcodes gallery. if ( preg_match_all( '/gallery_ids="(?P\w+[^"]*)"/i', $value, $matches ) ) { foreach ( array_unique( $matches['ids'] ) as $galleries ) { $explode = explode( ',', str_replace( ' ', '', $galleries ) ); foreach ( $explode as $image_id ) { $images = array_merge( $images, $this->get_data_images( array( (int) $image_id ), true ) ); } } } if ( preg_match( '/^.+?\.(jpg|jpeg|jpe|png|gif|svg|webp)/', $value, $match ) || $force ) { $basename = basename( $value ); // Skip if the value is not a valid URL or an image ID (integer). if ( ! ( wp_http_validate_url( $value ) || is_int( $value ) ) ) { continue; } // Skip if the images array already contains the value to avoid duplicates. if ( isset( $images[$value] ) ) { continue; } $images[$value] = $value; } } return $images; } /** * Get the attachment post id for the given url. * * @since 3.22.3 * * @param string $url The url of an attachment file. * * @return int */ protected function _get_attachment_id_by_url( $url ) { global $wpdb; // Remove any thumbnail size suffix from the filename and use that as a fallback. $fallback_url = preg_replace( '/-\d+x\d+(\.[^.]+)$/i', '$1', $url ); // Scenario: Trying to find the attachment for a file called x-150x150.jpg. // 1. Since WordPress adds the -150x150 suffix for thumbnail sizes we cannot be // sure if this is an attachment or an attachment's generated thumbnail. // 2. Since both x.jpg and x-150x150.jpg can be uploaded as separate attachments // we must decide which is a better match. // 3. The above is why we order by guid length and use the first result. $attachments_query = $wpdb->prepare( " SELECT id FROM $wpdb->posts WHERE `post_type` = %s AND `guid` IN ( %s, %s ) ORDER BY CHAR_LENGTH( `guid` ) DESC ", 'attachment', esc_url_raw( $url ), esc_url_raw( $fallback_url ) ); $attachment_id = (int) $wpdb->get_var( $attachments_query ); return $attachment_id; } /** * Encode image in a base64 format. * * @since 2.7.0 * * @param array $images Array of data for which images need to be encoded if any. * * @return array */ protected function encode_images( $images ) { $encoded = array(); foreach ( $images as $url ) { $id = 0; $image = ''; if ( is_int( $url ) ) { $id = $url; $url = wp_get_attachment_url( $id ); } else { $id = $this->_get_attachment_id_by_url( $url ); } if ( $id > 0 ) { $image = $this->_encode_attachment_image( $id ); } if ( empty( $image ) ) { // Case 1: No attachment found. // Case 2: Attachment found, but file does not exist (may be stored on a CDN, for example). $image = $this->_encode_remote_image( $url ); } if ( empty( $image ) ) { // All fetching methods have failed - bail on encoding. continue; } $encoded[ $url ] = array( 'encoded' => $image, 'url' => $url, ); // Add image id for replacement purposes. if ( $id > 0 ) { $encoded[ $url ]['id'] = $id; } } return $encoded; } /** * Encode an image attachment. * * @since 3.22.3 * * @param int $id * * @return string */ protected function _encode_attachment_image( $id ) { /** * @var WP_Filesystem_Base $wp_filesystem */ global $wp_filesystem; if ( ! current_user_can( 'read_post', $id ) ) { return ''; } $file = get_attached_file( $id ); if ( ! $wp_filesystem->exists( $file ) ) { return ''; } $image = $wp_filesystem->get_contents( $file ); if ( empty( $image ) ) { return ''; } return base64_encode( $image ); } /** * Encode a remote image. * * @since 3.22.3 * * @param string $url * * @return string */ protected function _encode_remote_image( $url ) { $request = wp_remote_get( esc_url_raw( $url ), array( 'timeout' => 2, 'redirection' => 2, ) ); if ( ! is_array( $request ) || is_wp_error( $request ) ) { return ''; } if ( ! self::$_->includes( $request['headers']['content-type'], 'image' ) ) { return ''; } $image = wp_remote_retrieve_body( $request ); if ( ! $image ) { return ''; } return base64_encode( $image ); } /** * Decode base64 formatted image and upload it to WP media. * * @since 2.7.0 * * @param array $images Array of encoded images which needs to be uploaded. * * @return array */ protected function upload_images( $images ) { $filesystem = $this->set_filesystem(); /** * Filters whether or not to allow duplicate images to be uploaded * during Portability import. * * @since 4.14.8 * * @param bool $allow_duplicates Whether or not to allow duplicates. Default is `false`. */ $allow_duplicates = apply_filters( 'et_core_portability_import_attachment_allow_duplicates', false ); foreach ( $images as $key => $image ) { $basename = sanitize_file_name( wp_basename( $image['url'] ) ); $id = 0; $url = ''; if ( ! $allow_duplicates ) { $attachments = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'attachment', 'meta_key' => '_wp_attached_file', 'meta_value' => pathinfo( $basename, PATHINFO_FILENAME ), 'meta_compare' => 'LIKE', ) ); // Avoid duplicates. if ( ! is_wp_error( $attachments ) && ! empty( $attachments ) ) { foreach ( $attachments as $attachment ) { $attachment_url = wp_get_attachment_url( $attachment->ID ); $file = get_attached_file( $attachment->ID ); $filename = sanitize_file_name( wp_basename( $file ) ); // Use existing image only if the content matches. if ( $filesystem->get_contents( $file ) === base64_decode( $image['encoded'] ) ) { $id = isset( $image['id'] ) ? $attachment->ID : 0; $url = $attachment_url; break; } } } } // Create new image. if ( empty( $url ) ) { $temp_file = wp_tempnam(); $filesystem->put_contents( $temp_file, base64_decode( $image['encoded'] ) ); $filetype = wp_check_filetype_and_ext( $temp_file, $basename ); if ( ! $allow_duplicates && ! empty( $attachments ) && ! is_wp_error( $attachments ) ) { // Avoid further duplicates if the proper_filename matches an existing image. if ( isset( $filetype['proper_filename'] ) && $filetype['proper_filename'] !== $basename ) { foreach ( $attachments as $attachment ) { $attachment_url = wp_get_attachment_url( $attachment->ID ); $file = get_attached_file( $attachment->ID ); $filename = sanitize_file_name( wp_basename( $file ) ); if ( isset( $filename ) && $filename === $filetype['proper_filename'] ) { // Use existing image only if the basenames and content match. if ( $filesystem->get_contents( $file ) === $filesystem->get_contents( $temp_file ) ) { $id = isset( $image['id'] ) ? $attachment->ID : 0; $url = $attachment_url; $filesystem->delete( $temp_file ); break; } } } } } $file = array( 'name' => $basename, 'tmp_name' => $temp_file, ); $upload = media_handle_sideload( $file ); $attachment_id = is_wp_error( $upload ) ? 0 : $upload; /** * Fires when image attachments are created during portability import. * * @since 4.14.6 * * @param int $attachment_id The attachment id or 0 if attachment upload failed. */ do_action( 'et_core_portability_import_attachment_created', $attachment_id ); if ( ! is_wp_error( $upload ) ) { // Set the replacement as an id if the original image was set as an id (for gallery). $id = isset( $image['id'] ) ? $upload : 0; $url = wp_get_attachment_url( $upload ); } else { // Make sure the temporary file is removed if media_handle_sideload didn't take care of it. $filesystem->delete( $temp_file ); } } // Only declare the replace if a url is set. if ( $id > 0 ) { $images[$key]['replacement_id'] = $id; } if ( ! empty( $url ) ) { $images[$key]['replacement_url'] = $url; } unset( $url ); } return $images; } /** * Replace encoded image url with a real url * * @param $subject - The string to perform replacing for * @param array $image - The image settings * * @return string|string[]|null */ protected function replace_image_url( $subject, $image ) { if ( isset( $image['replacement_id'] ) && isset( $image['id'] ) ) { $search = $image['id']; $replacement = $image['replacement_id']; $subject = preg_replace( "/(gallery_ids=.*?){$search}(.*?)/", "\${1}{$replacement}\${2}", $subject ); } if ( isset( $image['url'] ) && isset( $image['replacement_url'] ) && $image['url'] !== $image['replacement_url'] ) { $search = $image['url']; $replacement = $image['replacement_url']; $subject = str_replace( $search, $replacement, $subject ); } return $subject; } /** * Replace image urls with newly uploaded images. * * @since 2.7.0 * * @param array $images Array of new images uploaded. * @param array $data Array of for which images url needs to be replaced. * * @return array|mixed|object */ protected function replace_images_urls( $images, $data ) { foreach ( $data as $post_id => &$post_data ) { foreach ( $images as $image ) { if ( is_array( $post_data ) ) { foreach ( $post_data as $post_param => &$param_value ) { if ( ! is_array( $param_value ) ) { $data[ $post_id ][ $post_param ] = $this->replace_image_url( $param_value, $image ); } } unset($param_value); } else { $data[ $post_id ] = $this->replace_image_url( $post_data, $image ); } } } unset($post_data); return $data; } /** * Validate data and remove any malicious code. * * @since 2.7.0 * * @param array $data Array of data which needs to be validated. * @param array $fields_validation Array of field and validation callback. * * @return array|bool */ protected function validate( $data, $fields_validation = array() ) { if ( ! is_array( $data ) ) { return false; } foreach ( $data as $key => $value ) { if ( empty( $value ) ) { continue; } if ( is_array( $value ) ) { $data[$key] = $this->validate( $value, $fields_validation ); } else { if ( isset( $fields_validation[$key] ) ) { // @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found $data[$key] = call_user_func( $fields_validation[$key], $value ); } else { if ( current_user_can( 'unfiltered_html' ) ) { $data[ $key ] = $value; } else { $data[ $key ] = wp_kses_post( $value ); } } } } return $data; } /** * Filters a variable with string filter * * @param mixed $data - Value to filter. * * @return mixed */ protected function _filter_post_data( $data ) { return filter_var( $data, FILTER_SANITIZE_STRING, FILTER_FLAG_NO_ENCODE_QUOTES ); } /** * Prevent import and export timeout or memory failure. * * @since 2.7.0 * * It doesn't need to be reset as in both case the request exit. */ protected function prevent_failure() { @set_time_limit( 0 ); // Increase memory which is safe at this stage of the request. if ( et_core_get_memory_limit() < 256 ) { @ini_set( 'memory_limit', '256M' ); } } /** * Set WP filesystem to direct. This should only be use to create a temporary file. * * @since 2.7.0 * * It is safe to do so since the created file is removed immediately after import. The method does'nt have * to be reset since the ajax query is exited. */ protected function set_filesystem() { global $wp_filesystem; add_filter( 'filesystem_method', array( $this, 'replace_filesystem_method' ) ); WP_Filesystem(); return $wp_filesystem; } /** * Proxy method for set_filesystem() to avoid calling it multiple times. * * @since 4.0 * * @return WP_Filesystem_Direct */ protected function get_filesystem() { static $filesystem = null; if ( null === $filesystem ) { $filesystem = $this->set_filesystem(); } return $filesystem; } /** * Check if a temporary file is register. Returns temporary file if it exists. * * @since 4.0 Made method public. * * @param string $id Unique id used when the temporary file was created. * @param string $group Group name in which files are grouped. * * @return bool|string */ public function has_temp_file( $id, $group ) { $temp_files = get_option( '_et_core_portability_temp_files', array() ); if ( isset( $temp_files[$group][$id] ) && file_exists( $temp_files[$group][$id] ) ) { return $temp_files[$group][$id]; } return false; } /** * Create a temp file and register it. * * @since 2.7.0 * @since 4.0 Made method public. Added $content parameter. * * @param string $id Unique id reference for the temporary file. * @param string $group Group name in which files are grouped. * @param string|bool $temp_file Path to the temporary file. False create a new temporary file. * * @return bool|string */ public function temp_file( $id, $group, $temp_file = false, $content = '' ) { $temp_files = get_option( '_et_core_portability_temp_files', array() ); if ( ! isset( $temp_files[$group] ) ) { $temp_files[$group] = array(); } if ( isset( $temp_files[$group][$id] ) && file_exists( $temp_files[$group][$id] ) ) { return $temp_files[$group][$id]; } $temp_file = $temp_file ? $temp_file : wp_tempnam(); $temp_files[$group][$id] = $temp_file; update_option( '_et_core_portability_temp_files', $temp_files, false ); if ( ! empty( $content ) ) { $this->get_filesystem()->put_contents( $temp_file, $content ); } return $temp_file; } /** * Get temp file contents or an empty string if it does not exist. * * @since 4.0 * * @param string $id Unique id used when the temporary file was created. * @param string $group Group name in which files are grouped. * * @return string */ public function get_temp_file_contents( $id, $group ) { $file = $this->has_temp_file( $id, $group ); if ( ! $file ) { return ''; } $content = $this->get_filesystem()->get_contents( $file ); return $content ? $content : ''; } /** * Delete all the temp files. * * @since 2.7.0 * * @param bool|string $group Group name in which files are grouped. Set to true to remove all groups and files. * @param array $defined_files Array or temoporary files to delete. No argument deletes all temp files. */ public function delete_temp_files( $group = false, $defined_files = false ) { $filesystem = $this->set_filesystem(); $temp_files = get_option( '_et_core_portability_temp_files', array() ); // Remove all temp files accross all groups if group is true. if ( $group === true ) { foreach( $temp_files as $group_id => $_group ) { $this->delete_temp_files( $group_id ); } } if ( ! isset( $temp_files[$group] ) ) { return; } $delete_files = ( is_array( $defined_files ) && ! empty( $defined_files ) ) ? $defined_files : $temp_files[$group]; foreach ( $delete_files as $id => $temp_file ) { if ( isset( $temp_files[$group][$id] ) && $filesystem->delete( $temp_files[$group][$id] ) ) { unset( $temp_files[$group][$id] ); } } if ( empty( $temp_files[$group] ) ) { unset( $temp_files[$group] ); } if ( empty( $temp_files ) ) { delete_option( '_et_core_portability_temp_files' ); } else { update_option( '_et_core_portability_temp_files', $temp_files, false ); } } /** * Set WP filesystem method to direct. * * @since 2.7.0 */ public function replace_filesystem_method() { return 'direct'; } /** * Get timestamp or create one if it isn't set. * * @since 2.7.0 */ public function get_timestamp() { et_core_nonce_verified_previously(); if ( isset( $_POST['timestamp'] ) && ! empty( $_POST['timestamp'] ) ) { return sanitize_text_field( $_POST['timestamp'] ); } return function_exists( 'hrtime' ) ? (string) hrtime( true ) : (string) microtime( true ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.hrtimeFound -- Intentional use of new PHP function } /** * Get Global Colors array from provided global_colors_info. * * @since 4.10.8 * * @param array $global_colors_info Array of global colors to process. * * @return array The list of the Global Colors for export. */ protected function _get_global_colors_data( $global_colors_info = array() ) { $global_color_ids = array_unique( array_keys( $global_colors_info ) ); if ( empty( $global_color_ids ) ) { return array(); } $all_global_colors = et_builder_get_all_global_colors(); $used_colors = array(); foreach ( $global_color_ids as $color_id ) { if ( isset( $all_global_colors[ $color_id ] ) ) { $color_data = array( $color_id, $all_global_colors[ $color_id ], ); $used_colors[] = $color_data; } } return $used_colors; } /** * Get List of global colors used in shortcode. * * @since 4.10.8 * * @param array $shortcode_object The multidimensional array representing a page structure. * @param array $used_global_colors List of global colors to merge with. * @param array $presets Object of presets. * * @return array - The list of the Global Colors. */ protected function _get_used_global_colors( $shortcode_object, $used_global_colors = array(), $presets = array() ) { foreach ( $shortcode_object as $module ) { if ( isset( $module['attrs']['global_colors_info'] ) ) { // Retrive global_colors_info from post meta, which saved as string[][]. $gc_info_prepared = str_replace( array( '[', ']' ), array( '[', ']' ), $module['attrs']['global_colors_info'] ); // Make sure we pass array to array_merge to avoid Fatal Error. $gc_info_array = json_decode( $gc_info_prepared, true ); $gc_info_array = is_array( $gc_info_array ) ? $gc_info_array : []; $used_global_colors = array_merge( $used_global_colors, $gc_info_array ); } if ( isset( $module['content'] ) && is_array( $module['content'] ) ) { $used_global_colors = array_merge( $used_global_colors, $this->_get_used_global_colors( $module['content'], $used_global_colors, $presets ) ); } } if ( ! empty( $presets ) ) { foreach ( $presets as $module_type => $module_presets ) { foreach ( $module_presets->presets as $preset_id => $preset ) { if ( isset( $preset->settings->global_colors_info ) ) { $used_global_colors = array_merge( $used_global_colors, json_decode( $preset->settings->global_colors_info, true ) ); } } } } return $used_global_colors; } /** * Returns Global Presets used for a given shortcode only * * @since 3.26 * * @param array $shortcode_object - The multidimensional array representing a page structure * @param array $used_global_presets * * @return array - The list of the Global Presets * */ protected function get_used_global_presets( $shortcode_object, $used_global_presets = array() ) { $global_presets_manager = ET_Builder_Global_Presets_Settings::instance(); foreach ( $shortcode_object as $module ) { $module_type = $global_presets_manager->maybe_convert_module_type( $module['type'], $module['attrs'] ); $preset_id = $global_presets_manager->get_module_preset_id( $module_type, $module['attrs'] ); $preset = $global_presets_manager->get_module_preset( $module_type, $preset_id ); if ( $preset_id !== 'default' && count( (array) $preset ) !== 0 && count( (array) $preset->settings ) !== 0 ) { if ( ! isset( $used_global_presets[ $module_type ] ) ) { $used_global_presets[ $module_type ] = (object) array( 'presets' => (object) array(), ); } if ( ! isset( $used_global_presets[ $module_type ]->presets->$preset_id ) ) { $used_global_presets[ $module_type ]->presets->$preset_id = (object) array( 'name' => $preset->name, 'version' => $preset->version, 'settings' => $preset->settings, ); } if ( ! isset( $used_global_presets[ $module_type ]->default ) ) { $used_global_presets[ $module_type ]->default = $global_presets_manager->get_module_default_preset_id( $module_type ); } } if ( isset( $module['content'] ) && is_array( $module['content'] ) ) { $used_global_presets = array_merge( $used_global_presets, $this->get_used_global_presets( $module['content'], $used_global_presets ) ); } } return $used_global_presets; } /** * Returns Global Colors used for a given theme builder shortcode. * * @since 4.18.0 * * @param array $shortcode_object - The multidimensional array representing a page structure. * * @return array The list of the Global Colors */ public function get_theme_builder_library_used_global_colors( $shortcode_object ) { return $this->_get_used_global_colors( $shortcode_object ); } /** * Returns Global Presets used for a given theme builder shortcode. * * @since 4.18.0 * * @param array $shortcode_object - The multidimensional array representing a page structure. * * @return array The list of the Global Presets */ public function get_theme_builder_library_used_global_presets( $shortcode_object ) { return $this->get_used_global_presets( $shortcode_object ); } /** * Returns images used for a given theme builder shortcode. * * @since 4.18.0 * * @param array $data - ID and Post content. * * @return array The list of the encoded images */ public function get_theme_builder_library_images( $data ) { $timestamp = $this->get_timestamp(); $images = $this->get_data_images( $data ); return $this->maybe_paginate_images( $images, 'encode_images', $timestamp ); } /** * Returns thumbnails used for a given theme builder shortcode. * * @since 4.18.0 * * @param array $data - ID and Post content. * * @return array The list of the thumbnails */ public function get_theme_builder_library_thumbnail_images( $data ) { return $this->_get_thumbnail_images( $data ); } /** * Enqueue assets. * * @since ?.? Script `et-core-portability` now loads in footer along with `et-core-admin`. * @since 2.7.0 */ public function assets() { $time = '1'; wp_enqueue_style( 'et-core-portability', ET_CORE_URL . 'admin/css/portability.css', array( 'et-core-admin', ), ET_CORE_VERSION ); wp_enqueue_script( 'et-core-portability', ET_CORE_URL . 'admin/js/portability.js', array( 'jquery', 'jquery-ui-tabs', 'jquery-form', 'et-core-admin', ), ET_CORE_VERSION, true ); wp_localize_script( 'et-core-portability', 'etCorePortability', array( 'nonces' => array( 'import' => wp_create_nonce( 'et_core_portability_import' ), 'export' => wp_create_nonce( 'et_core_portability_export' ), 'cancel' => wp_create_nonce( 'et_core_portability_cancel' ), 'presets' => wp_create_nonce( 'et_core_portability_import_default_presets' ), ), 'postMaxSize' => $this->to_megabytes( @ini_get( 'post_max_size' ) ), 'uploadMaxSize' => $this->to_megabytes( @ini_get( 'upload_max_filesize' ) ), 'text' => array( // phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralDomain -- Following the standard. 'browserSupport' => esc_html__( 'The browser version you are currently using is outdated. Please update to the newest version.', ET_CORE_TEXTDOMAIN ), 'memoryExhausted' => esc_html__( 'You reached your server memory limit. Please try increasing your PHP memory limit.', ET_CORE_TEXTDOMAIN ), 'maxSizeExceeded' => esc_html__( 'This file cannot be imported. It may be caused by file_uploads being disabled in your php.ini. It may also be caused by post_max_size or/and upload_max_filesize being smaller than file selected. Please increase it or transfer more substantial data at the time.', ET_CORE_TEXTDOMAIN ), 'invalideFile' => esc_html__( 'Invalid File format. You should be uploading a JSON file.', ET_CORE_TEXTDOMAIN ), 'importContextFail' => esc_html__( 'This file should not be imported in this context.', ET_CORE_TEXTDOMAIN ), 'noItemsSelected' => esc_html__( 'Please select at least one item to export or disable the "Only export selected items" option', ET_CORE_TEXTDOMAIN ), 'noItemsToExport' => esc_html__( 'There are no items to export.', ET_CORE_TEXTDOMAIN ), 'importing' => sprintf( esc_html__( 'Import estimated time remaining: %smin', ET_CORE_TEXTDOMAIN ), $time ), 'exporting' => sprintf( esc_html__( 'Export estimated time remaining: %smin', ET_CORE_TEXTDOMAIN ), $time ), 'backuping' => sprintf( esc_html__( 'Backup estimated time remaining: %smin', ET_CORE_TEXTDOMAIN ), $time ), // phpcs:enable ), ) ); } /** * Modal HTML. * * @since 2.7.0 */ public function modal() { $export_url = add_query_arg( array( 'et_core_portability' => true, 'context' => $this->instance->context, 'name' => $this->instance->name, 'nonce' => wp_create_nonce( 'et_core_portability_export' ), ), admin_url() ); $is_etdev_plugin_activated = is_plugin_active( 'etdev/etdev.php' ); // phpcs:disable WordPress.WP.I18n.NonSingularStringLiteralDomain -- Existing codebase. ?>

instance->title ); ?>

instance->name ) ); ?>

instance->type ) : ?>
instance->context ) { ?>
instance->type ) : ?> instance->name ) ); ?> instance->type ) : ?> instance->name ) ); ?> instance->name ) ); ?>

instance->type ) : ?> instance->type ) : ?>
instance->name ) ); ?>
$context, 'title' => esc_html__( 'Portability', ET_CORE_TEXTDOMAIN ), // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralDomain -- intentional use of ET_CORE_TEXTDOMAIN 'name' => false, 'view' => false, 'type' => false, 'target' => false, 'include' => array(), 'exclude' => array(), ); $data = apply_filters( "et_core_portability_args_{$context}", (object) array_merge( $defaults, (array) $args ) ); et_core_cache_set( $context, $data, 'et_core_portability' ); // Stop here if not allowed. if ( function_exists( 'et_pb_is_allowed' ) && ! et_pb_is_allowed( array( 'portability', "{$data->context}_portability" ) ) ) { // Set view to false if not allowed. $data->view = false; et_core_cache_set( $context, $data, 'et_core_portability' ); return; } if ( $data->view ) { et_core_portability_load( $context ); } } endif; if ( ! function_exists( 'et_core_portability_load' ) ) : /** * Load Portability class. * * @since 2.7.0 * * @param string $context A unique ID used to register the portability arguments. * @return ET_Core_Portability */ function et_core_portability_load( $context ) { return new ET_Core_Portability( $context ); } endif; if ( ! function_exists( 'et_core_portability_link' ) ) : /** * HTML link to trigger the portability modal. * * @since 2.7.0 * * @param string $context The context used to register the portability. * @param string|array $attributes Optional. Query string or array of attributes. Default empty. * * @return string */ function et_core_portability_link( $context, $attributes = array() ) { $instance = et_core_cache_get( $context, 'et_core_portability' ); if ( ! $capability = et_core_portability_cap( $context ) ) { return ''; } if ( ! current_user_can( $capability ) || ! ( isset( $instance->view ) && $instance->view ) ) { return ''; } $defaults = array( 'title' => esc_attr__( 'Import & Export', ET_CORE_TEXTDOMAIN ), ); $attributes = array_merge( $defaults, $attributes ); // Forced attributes. $attributes['href'] = '#'; $context = esc_attr( $context ); $attributes['data-et-core-modal'] = "[data-et-core-portability='{$context}']"; $string = ''; foreach ( $attributes as $attribute => $value ) { if ( null !== $value ){ $string .= esc_attr( $attribute ) . '="' . esc_attr( $value ) . '" '; } } return sprintf( '%2$s', trim( $string ), esc_html( $attributes['title'] ) ); } endif; if ( ! function_exists( 'et_core_portability_ajax_import' ) ) : /** * Ajax portability Import. * * @since 2.7.0 */ function et_core_portability_ajax_import() { if ( ! isset( $_POST['context'] ) ) { et_core_die(); } $context = sanitize_text_field( $_POST['context'] ); $post_id = isset( $_POST['post'] ) ? (int) $_POST['post'] : 0; $replace = isset( $_POST['replace'] ) ? '1' === $_POST['replace'] : false; if ( ! $capability = et_core_portability_cap( $context ) ) { et_core_die(); } if ( ! et_core_security_check_passed( $capability, 'et_core_portability_import', 'nonce' ) ) { et_core_die(); } $portability = et_core_portability_load( $context ); if ( ! $result = $portability->import() ) { wp_send_json_error(); } else if ( is_array( $result ) && isset( $result['message'] ) ) { wp_send_json_error( $result ); } else if ( $result ) { if ( $replace && $post_id > 0 && current_user_can( 'edit_post', $post_id ) ) { wp_update_post( array( 'ID' => $post_id, 'post_content' => $result['postContent'], ) ); } wp_send_json_success( $result ); } wp_send_json_error(); } add_action( 'wp_ajax_et_core_portability_import', 'et_core_portability_ajax_import' ); endif; if ( ! function_exists( 'et_core_portability_ajax_export' ) ) : /** * Ajax portability Export. * * @since 2.7.0 */ function et_core_portability_ajax_export() { if ( ! isset( $_POST['context'] ) ) { wp_send_json_error(); return; } $context = sanitize_text_field( $_POST['context'] ); // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure, WordPress.CodeAnalysis.AssignmentInCondition.Found -- Existing codebase. if ( ! $capability = et_core_portability_cap( $context ) ) { wp_send_json_error(); return; } if ( ! et_core_security_check_passed( $capability, 'et_core_portability_export', 'nonce' ) ) { wp_send_json_error(); return; } $return = isset( $_POST['return'] ) && sanitize_text_field( $_POST['return'] ); if ( $return ) { $data = et_core_portability_load( $context )->export( $return ); wp_send_json_success( $data ); } else { et_core_portability_load( $context )->export(); } wp_send_json_error(); } add_action( 'wp_ajax_et_core_portability_export', 'et_core_portability_ajax_export' ); endif; if ( ! function_exists( 'et_core_portability_ajax_cancel' ) ) : /** * Cancel portability action. * * @since 2.7.0 */ function et_core_portability_ajax_cancel() { if ( ! isset( $_POST['context'] ) ) { et_core_die(); } $context = sanitize_text_field( $_POST['context'] ); if ( ! $capability = et_core_portability_cap( $context ) ) { et_core_die(); } if ( ! et_core_security_check_passed( $capability, 'et_core_portability_cancel' ) ) { et_core_die(); } et_core_portability_load( $context )->delete_temp_files( true ); wp_send_json_error(); } add_action( 'wp_ajax_et_core_portability_cancel', 'et_core_portability_ajax_cancel' ); endif; if ( ! function_exists( 'et_core_upload_and_get_urls_from_presets_images' ) ) : /** * Upload images and return the new URLs for presets. * * @since 4.26.1 * @param array $data Array of images to upload. * * @return array */ function et_core_upload_and_get_urls_from_presets_images( $data ) { if ( ! current_user_can( 'manage_options' ) ) { return; } // Require the file that includes wp_generate_attachment_metadata(). require_once( ABSPATH . 'wp-admin/includes/image.php' ); $mime_types = get_allowed_mime_types(); $wp_upload_dir = wp_upload_dir(); $uploaded_urls = []; foreach ( $data as $imageInfo ) { $image_data = base64_decode( $imageInfo['encoded'] ); $temp_file = tempnam( $wp_upload_dir['path'], 'preset_' ); $filetype = wp_check_filetype( basename( $temp_file ), null ); if ( ! in_array( $filetype['type'], $mime_types, true ) ) { continue; } file_put_contents( $temp_file, $image_data ); $attachment = [ 'guid' => $wp_upload_dir['url'] . '/' . basename( $temp_file ), 'post_mime_type' => $filetype['type'], 'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $temp_file ) ), 'post_content' => '', 'post_status' => 'inherit' ]; $attach_id = wp_insert_attachment( $attachment, $temp_file ); $attach_data = wp_generate_attachment_metadata( $attach_id, $temp_file ); wp_update_attachment_metadata( $attach_id, $attach_data ); $uploaded_urls[] = [ 'old_url' => $imageInfo['url'], 'new_url' => wp_get_attachment_url( $attach_id ), ]; unlink( $temp_file ); } return $uploaded_urls; } endif; if ( ! function_exists( 'et_core_replace_image_urls_in_presets' ) ) : /** * Replace image URLs in presets JSON string. */ function et_core_replace_image_urls_in_presets( $presets, $uploaded_urls ) { foreach ( $uploaded_urls as $url ) { $presets = str_replace( $url['old_url'], $url['new_url'], $presets ); } return $presets; } endif; if ( ! function_exists( 'et_core_portability_import_default_presets' ) ) : /** * Set the default preset for a modules. * * @since 4.26.0 */ function et_core_portability_import_default_presets() { if ( ! et_core_security_check_passed( 'manage_options', 'et_core_portability_import_default_presets', 'nonce' ) ) { et_core_die(); } $presets = isset( $_POST['presets'] ) ? sanitize_text_field( $_POST['presets'] ) : ''; $preset_prefix = isset( $_POST['presetPrefix'] ) ? sanitize_text_field( $_POST['presetPrefix'] ) : ''; $global_colors = isset( $_POST['globalColors'] ) ? sanitize_text_field( $_POST['globalColors'] ) : ''; $images = isset( $_POST['images'] ) ? sanitize_text_field( $_POST['images'] ) : ''; $uploaded_urls = []; $portability = et_core_portability_load( 'et_builder' ); if ( $global_colors ) { $global_colors = json_decode( stripslashes( $global_colors ), true ); $portability->import_global_colors( $global_colors ); } if ( $images ) { $images = json_decode( stripslashes( $images ), true ); $uploaded_urls = et_core_upload_and_get_urls_from_presets_images( $images ); } if ( $presets ) { if ( ! empty( $uploaded_urls ) ) { $presets = et_core_replace_image_urls_in_presets( $presets, $uploaded_urls ); } $presets = json_decode( stripslashes( $presets ), true ); $portability->import_global_presets( $presets, false, true, $preset_prefix ); } ET_Core_PageResource::remove_static_resources( 'all', 'all' ); wp_send_json_success(); } add_action( 'wp_ajax_et_core_portability_import_default_presets', 'et_core_portability_import_default_presets' ); endif; if ( ! function_exists( 'et_core_portability_export' ) ) : /** * Portability export. * * @since 2.7.0 */ function et_core_portability_export() { if ( ! isset( $_GET['et_core_portability'], $_GET['timestamp'] ) ) { return; } if ( ! et_core_security_check_passed( 'edit_posts' ) ) { wp_die( esc_html__( 'The export process failed. Please refresh the page and try again.', ET_CORE_TEXTDOMAIN ) ); } et_core_portability_load( sanitize_text_field( $_GET['timestamp'] ) )->download_export(); } add_action( 'admin_init', 'et_core_portability_export', 20 ); endif; if ( ! function_exists( 'et_core_portability_cap' ) ): /** * Returns the required WordPress Capability for a Portability context. * * @since 3.0.91 * * @param string $context The Portability context * * @return string */ function et_core_portability_cap( $context ) { $capability = ''; $options_contexts = array( 'et_pb_roles', 'epanel', 'epanel_temp', 'et_divi_mods', 'et_extra_mods', ); $post_contexts = array( 'et_builder', 'et_theme_builder', 'et_code_snippets', 'et_builder_layouts', ); if ( in_array( $context, $options_contexts, true ) ) { $capability = 'edit_theme_options'; } else if ( in_array( $context, $post_contexts, true ) ) { $capability = 'edit_posts'; } return $capability; } endif; PKE\kcomponents/SupportCenter.phpnu[ * @license GNU General Public License v2 * * @since 3.24.1 Renamed from `ET_Support_Center` to `ET_Core_SupportCenter`. * @since 3.20 */ class ET_Core_SupportCenter { /** * Catch whether the ET_DEBUG flag is set. * * @since 3.20 * * @type string */ protected $DEBUG_ET_SUPPORT_CENTER = false; /** * Identifier for the parent theme or plugin activating the Support Center. * * @since 3.20 * * @type string */ protected $parent = ''; /** * "Nice name" for the parent theme or plugin activating the Support Center. * * @since 3.20 * * @type string */ protected $parent_nicename = ''; /** * Whether the Support Center was activated through a `plugin` or a `theme`. * * @since 3.20 * * @type string */ protected $child_of = ''; /** * Identifier for the parent theme or plugin activating the Support Center. * * @since 3.20 * * @type string */ protected $local_path; /** * Support User options * * @since 3.20 * * @type array */ protected $support_user_options; /** * Support User account name * * @since 3.20 * * @type string */ protected $support_user_account_name = 'elegant_themes_support'; /** * Support options name in the database * * @since 3.20 * * @type string */ protected $support_user_options_name = 'et_support_options'; /** * Name of the cron job we use to auto-delete the Support User account * * @since 3.20 * * @type string */ protected $support_user_cron_name = 'et_cron_delete_support_account'; /** * Expiration time to auto-delete the Support User account via cron * * @since 3.20 * * @type string */ protected $support_user_expiration_time = '+4 days'; /** * Provide nicename equivalents for boolean values * * @since 3.23 * * @type array */ protected $boolean_label = array( 'False', 'True' ); /** * Collection of plugins that we will NOT disable when Safe Mode is activated. * * @since 3.20 * * @type array */ protected $safe_mode_plugins_allowlist = array( 'etdev/etdev.php', // ET Development Workspace 'bloom/bloom.php', // ET Bloom Plugin 'monarch/monarch.php', // ET Monarch Plugin 'divi-builder/divi-builder.php', // ET Divi Builder Plugin 'divi-dash/divi-dash.php', // Divi Dash Plugin 'ari-adminer/ari-adminer.php', // ARI Adminer 'query-monitor/query-monitor.php', // Query Monitor 'woocommerce/woocommerce.php', // WooCommerce 'really-simple-ssl/rlrsssl-really-simple-ssl.php', // Really Simple SSL ); /** * Capabilities that should be granted to the Administrator role on activation. * * @since 3.28 * * @type array */ protected $support_center_administrator_caps = array( 'et_support_center', 'et_support_center_system', 'et_support_center_remote_access', 'et_support_center_documentation', 'et_support_center_safe_mode', 'et_support_center_logs', ); /** * Collection of Cards that has button to dismiss the Card. * * @since 4.4.7 * * @type array */ protected $card_with_dismiss_button = array( 'et_hosting_card', ); /** * Core functionality of the class * * @since 4.4.7 Added WP AJAX action for dismissible button for a card * @since 3.20 * * @param string $parent Identifier for the parent theme or plugin activating the Support Center. */ public function __construct( $parent = '' ) { // Verbose logging: only log if `wp-config.php` has defined `ET_DEBUG='support_center'` $this->DEBUG_ET_SUPPORT_CENTER = defined( 'ET_DEBUG' ) && 'support_center' === ET_DEBUG; // Set the identifier for the parent theme or plugin activating the Support Center. $this->parent = $parent; // Get `et_support_options` settings & set $this->support_user_options $this->support_user_get_options(); // Set the plugins allowlist for Safe Mode $this->set_safe_mode_plugins_allowlist(); } /** * WordPress action & filter setup * * @since 3.20 */ public function init() { update_option( 'et_support_center_installed', 'true' ); // Establish which theme or plugin has loaded the Support Center $this->set_parent_properties(); // When initialized, deactivate conflicting plugins $this->deactivate_conflicting_plugins(); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts_styles' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) ); // SC scripts are only used in FE for the "Turn Off Divi Safe Mode" floating button. if ( et_core_is_safe_mode_active() ) { add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts_styles' ) ); } // Get Site ID with Elegant Themes API & token (needed in advance for Remote Access). add_action( 'admin_init', array( $this, 'maybe_set_site_id' ) ); // Add extra User Role capabilities needed for Remote Access to work with 3rd party software add_filter( 'add_et_support_standard_capabilities', array( $this, 'support_user_extra_caps_standard' ), 10, 1 ); add_filter( 'add_et_support_elevated_capabilities', array( $this, 'support_user_extra_caps_elevated' ), 10, 1 ); // Make sure that our Support Account's roles are set up add_filter( 'add_et_builder_role_options', array( $this, 'support_user_add_role_options' ), 10, 1 ); // On Multisite installs, grant `unfiltered_html` capabilities to the Support User add_filter( 'map_meta_cap', array( $this, 'support_user_map_meta_cap' ), 1, 3 ); // Add CSS class name(s) to the Support Center page's body tag add_filter( 'admin_body_class', array( $this, 'add_admin_body_class_name' ) ); // Add a link to the Support Center in the admin menu add_filter( 'admin_menu', array( $this, 'add_admin_menu_item' ) ); // When Safe Mode is enabled, add floating frontend indicator add_action( 'admin_footer', array( $this, 'maybe_add_safe_mode_indicator' ) ); add_action( 'wp_footer', array( $this, 'maybe_add_safe_mode_indicator' ) ); // Add User capabilities to the Administrator Role add_action( 'admin_init', array( $this, 'support_center_capabilities_setup' ) ); if ( 'plugin' === $this->child_of ) { // Delete our Support User settings on deactivation register_deactivation_hook( __FILE__, array( $this, 'support_user_delete_account' ) ); register_deactivation_hook( __FILE__, array( $this, 'unlist_support_center' ) ); register_deactivation_hook( __FILE__, array( $this, 'support_center_capabilities_teardown' ) ); } if ( 'theme' === $this->child_of ) { // Delete our Support User settings on deactivation add_action( 'switch_theme', array( $this, 'maybe_deactivate_on_theme_switch' ) ); } // Automatically delete our Support User when the time runs out add_action( $this->support_user_cron_name, array( $this, 'support_user_cron_maybe_delete_account' ) ); add_action( 'init', array( $this, 'support_user_maybe_delete_expired_account' ) ); add_action( 'admin_init', array( $this, 'support_user_maybe_delete_expired_account' ) ); // Remove KSES filters for ET Support User add_action( 'admin_init', array( $this, 'support_user_kses_remove_filters' ) ); // Update Support User settings via AJAX add_action( 'wp_ajax_et_support_user_update', array( $this, 'support_user_update_via_ajax' ) ); // Toggle Safe Mode via AJAX add_action( 'wp_ajax_et_safe_mode_update', array( $this, 'safe_mode_update_via_ajax' ) ); // Safe Mode: Block restricted actions when Safe Mode active add_action( 'admin_footer', array( $this, 'render_safe_mode_block_restricted' ) ); // Safe Mode: Temporarily disable Custom CSS add_action( 'init', array( $this, 'maybe_disable_custom_css' ) ); // Safe Mode: Remove "Additional CSS" from WP Head action hook if ( et_core_is_safe_mode_active() ) { remove_action( 'wp_head', 'wp_custom_css_cb', 101 ); } // Support Center Card: Handle Dismiss Button add_action( 'wp_ajax_et_dismiss_support_center_card', array( $this, 'dismiss_support_center_card_via_ajax' ) ); } /** * Add User capabilities to the Administrator Role (if it exists) on first run * * @since 3.29.2 Added check to verify the Administrator Role exists before attempting to run `add_cap()`. * @since 3.28 */ public function support_center_capabilities_setup() { $support_capabilities = get_option( 'et_support_center_setup_done' ); $administrator_role = get_role( 'administrator' ); if ( $administrator_role && ! $support_capabilities ) { foreach ( $this->support_center_administrator_caps as $cap ) { $administrator_role->add_cap( $cap ); } update_option( 'et_support_center_setup_done', 'processed' ); } } /** * Remove User capabilities from the Administrator Role when product with Support Center is removed * * @since 3.29.2 Added check to verify the Administrator Role exists before attempting to run `remove_cap()`. * @since 3.28 */ public function support_center_capabilities_teardown() { $support_capabilities = get_option( 'et_support_center_setup_done' ); $administrator_role = get_role( 'administrator' ); if ( $administrator_role && $support_capabilities ) { foreach ( $this->support_center_administrator_caps as $cap ) { $administrator_role->remove_cap( $cap ); } delete_option( 'et_support_center_setup_done' ); } } /** * Set variables that change depending on whether a theme or a plugin activated the Support Center * * @since 3.20 */ public function set_parent_properties() { $core_path = _et_core_normalize_path( trailingslashit( dirname( __FILE__ ) ) ); $theme_dir = _et_core_normalize_path( trailingslashit( realpath( get_template_directory() ) ) ); if ( 0 === strpos( $core_path, $theme_dir ) ) { $this->child_of = 'theme'; $this->local_path = trailingslashit( get_template_directory_uri() . '/core/' ); } else { $this->child_of = 'plugin'; $this->local_path = plugins_url( '/', dirname( __FILE__ ) ); } $this->parent_nicename = $this->get_parent_nicename( $this->parent ); } /** * Get the "Nice Name" for the parent theme/plugin * * @param $parent * * @return bool|string */ public function get_parent_nicename( $parent ) { switch ( $parent ) { case 'bloom_plugin': return 'Bloom'; break; case 'monarch_plugin': return 'Monarch'; break; case 'extra_theme': return 'Extra'; break; case 'divi_theme': return 'Divi'; break; case 'divi_builder_plugin': return 'Divi Builder'; break; case 'divi_dash_plugin': return 'Divi Dash'; break; default: return false; } } /** * Prevent any possible conflicts with the Elegant Themes Support plugin * * @since 3.20 */ public function deactivate_conflicting_plugins() { require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); // Load WP user management functions if ( is_multisite() ) { require_once( ABSPATH . 'wp-admin/includes/ms.php' ); } else { require_once( ABSPATH . 'wp-admin/includes/user.php' ); } // Verify that WP user management functions are available $can_delete_user = false; if ( is_multisite() && function_exists( 'wpmu_delete_user' ) ) { $can_delete_user = true; } if ( ! is_multisite() && function_exists( 'wp_delete_user' ) ) { $can_delete_user = true; } if ( $can_delete_user ) { deactivate_plugins( '/elegant-themes-support/elegant-themes-support.php' ); } else { et_error( 'Support Center: Unable to deactivate the ET Support Plugin.' ); } } /** * @param string $capability * * @return bool */ protected function current_user_can( $capability = '' ) { if ( function_exists( 'et_is_builder_plugin_active' ) ) { return et_pb_is_allowed( $capability ); } return current_user_can( $capability ); } /** * Add Safe Mode Autoloader Must-Use Plugin * * @since 3.20 */ public function maybe_add_mu_autoloader() { $file_name = '/SupportCenterMUAutoloader.php'; $file_path = dirname( __FILE__ ); // Exit if the `mu-plugins` directory doesn't exist & we're unable to create it if ( ! wp_mkdir_p( WPMU_PLUGIN_DIR ) ) { et_error( 'Support Center Safe Mode: mu-plugin folder not found.' ); return; } $pathname_to = WPMU_PLUGIN_DIR . $file_name; $pathname_from = $file_path . $file_name; // Exit if we can't find the mu-plugins autoloader if ( ! file_exists( $pathname_from ) ) { et_error( 'Support Center Safe Mode: mu-plugin autoloader not found.' ); return; } // Try to create a new subdirectory for our mu-plugins; if it fails, log an error message $pathname_plugins_from = dirname( __FILE__ ) . '/mu-plugins'; $pathname_plugins_to = WPMU_PLUGIN_DIR . '/et-safe-mode'; if ( ! wp_mkdir_p( $pathname_plugins_to ) ) { et_error( 'Support Center Safe Mode: mu-plugins subfolder not found.' ); return; } // Try to copy the mu-plugins; if any fail, log an error message if ( $mu_plugins = glob( dirname( __FILE__ ) . '/mu-plugins/*.php' ) ) { foreach ( $mu_plugins as $plugin ) { $new_file_path = str_replace( $pathname_plugins_from, $pathname_plugins_to, $plugin ); // Skip if this particular mu-plugin hasn't changed if ( file_exists( $new_file_path ) && md5_file( $new_file_path ) === md5_file( $plugin ) ) { continue; } $copy_file = @copy( $plugin, $new_file_path ); if ( ! $this->DEBUG_ET_SUPPORT_CENTER ) { continue; } if ( $copy_file ) { et_error( 'Support Center Safe Mode: mu-plugin [' . $plugin . '] installed.' ); } else { et_error( 'Support Center Safe Mode: mu-plugin [' . $plugin . '] failed installation. ' ); } } } // Finally, try to copy the autoloader file; if it fails, log an error message // Skip if the mu-plugins autoloader hasn't changed if ( file_exists( $pathname_to ) && md5_file( $pathname_to ) === md5_file( $pathname_from ) ) { return; } $copy_file = @copy( $pathname_from, $pathname_to ); if ( $this->DEBUG_ET_SUPPORT_CENTER ) { if ( $copy_file ) { et_error( 'Support Center Safe Mode: mu-plugin installed.' ); } else { et_error( 'Support Center Safe Mode: mu-plugin failed installation. ' ); } } } public function maybe_remove_mu_autoloader() { @unlink( WPMU_PLUGIN_DIR . '/SupportCenterMUAutoloader.php' ); @unlink( WPMU_PLUGIN_DIR . '/et-safe-mode/SupportCenterSafeModeDisablePlugins.php' ); et_()->remove_empty_directories( WPMU_PLUGIN_DIR . '/et-safe-mode' ); } /** * Update the Site ID data via Elegant Themes API * * @since ?.? Early exit if no Site ID, but also no API credentials to use for a request. * @since 3.20 * * @return void */ public function maybe_set_site_id() { // Early exit if the user doesn't have Support Center access. if ( ! $this->current_user_can( 'et_support_center' ) ) { return; } $site_id = get_option( 'et_support_site_id' ); // If we already have a saved Site ID for support, then we don't need to request a new ID. if ( ! empty( $site_id ) ) { return; } // If there are no saved API credentials, then we can't use the API to request a Site ID for support. if ( ! $this->get_et_license() ) { return; } $site_id = ''; $send_to_api = array( 'action' => 'get_site_id', ); $settings = array( 'timeout' => 30, 'body' => $send_to_api, ); $request = wp_remote_post( 'https://www.elegantthemes.com/api/token.php', $settings ); if ( ! is_wp_error( $request ) && 200 == wp_remote_retrieve_response_code( $request ) ) { $response = unserialize( wp_remote_retrieve_body( $request ) ); if ( ! empty( $response['site_id'] ) ) { $site_id = esc_attr( $response['site_id'] ); } } update_option( 'et_support_site_id', $site_id ); } /** * Safe Mode temporarily deactivates all plugins *except* those in the allowlist option set here * * @since 3.20 * * @return void */ public function set_safe_mode_plugins_allowlist() { update_option( 'et_safe_mode_plugins_allowlist', $this->safe_mode_plugins_allowlist ); } /** * Add Support Center menu item (but only if it's enabled for current user) * * When initialized we were given an identifier for the plugin or theme doing the initializing. We're going to use * that identifier here to insert the Support Center menu item in the correct location within the WP Admin Menu. * * @since 3.28 Expanded sub-menu links with support for additional ET products. * @since 3.20 */ public function add_admin_menu_item() { // Early exit if the user doesn't have Support Center access if ( ! $this->current_user_can( 'et_support_center' ) ) { return; } $menu_title = esc_html__( 'Support Center', 'et-core' ); $menu_slug = null; $parent_menu_slug = null; // By default, only user with `manage_options` capability which is "administrator" // can see Support Center menu and access the page. $capability = 'manage_options'; // Define parent and child menu slugs switch ( $this->parent ) { case 'bloom_plugin': $menu_slug = 'et_support_center_bloom'; $parent_menu_slug = 'et_bloom_options'; break; case 'monarch_plugin': $menu_title = esc_html__( 'Monarch Support Center', 'et-core' ); $menu_slug = 'et_support_center_monarch'; $parent_menu_slug = 'tools.php'; break; case 'extra_theme': $menu_slug = 'et_support_center_extra'; $parent_menu_slug = 'et_extra_options'; break; case 'divi_theme': case 'divi_builder_plugin': // In the Roles Editor, other user roles may have access to the Support Center. // But, most likely they don't have `manage_options` capability. So, if current // user can't `manage_options`, we will set the submenu capability into the // `edit_theme_options`, so other roles with `edit_theme_options` capability // can access the Support Center. if ( ! current_user_can( 'manage_options' ) ) { $capability = 'edit_theme_options'; } // However, that's not enough. We still need to check whether current user with // `manage_options` or `edit_theme_options` is allowed to access Support Center. if ( ! et_pb_is_allowed( 'support_center' ) ) { return; } $menu_slug = 'et_support_center_divi'; $parent_menu_slug = 'et_divi_options'; } // If there's no menu slug, then this product doesn't have Support Center enabled if ( ! $menu_slug ) { return; } // Build the link add_submenu_page( $parent_menu_slug, $menu_title, $menu_title, $capability, $menu_slug, array( $this, 'add_support_center' ) ); } /** * Add class name to Support Center page * * @since 3.20 * * @param string $admin_classes Current class names for the body tag. * * @return string */ public function add_admin_body_class_name( $admin_classes = '' ) { $classes = explode( ' ', $admin_classes ); $classes[] = 'et-admin-page'; if ( et_core_is_safe_mode_active() ) { $classes[] = 'et-safe-mode-active'; } return implode( ' ', $classes ); } /** * Support Center admin page JS * * @since 3.20 * * @param $hook string Unique identifier for WP admin page. * * @return void */ public function admin_enqueue_scripts_styles( $hook ) { et_core_register_admin_assets(); wp_enqueue_style( 'et-core-admin' ); wp_enqueue_script( 'et-core-admin' ); // Load only on `_et_support_center` pages. if ( strpos( $hook, '_et_support_center' ) ) { // Core Admin CSS wp_enqueue_style( 'et-core', $this->local_path . 'admin/css/core.css', array(), ET_CORE_VERSION ); // ePanel CSS wp_enqueue_style( 'et-wp-admin', $this->local_path . 'admin/css/wp-admin.css', array(), ET_CORE_VERSION ); // Support Center CSS wp_enqueue_style( 'et-support-center', $this->local_path . 'admin/css/support-center.css', array(), ET_CORE_VERSION ); // Support Center uses ePanel controls, so include the necessary scripts if ( function_exists( 'et_core_enqueue_js_admin' ) ) { et_core_enqueue_js_admin(); } } } /** * Support Center frontend CSS/JS * * @since 3.20 * * @param $hook string Unique identifier for WP admin page. * * @return void */ public function enqueue_scripts_styles( $hook ) { // We only need to add this for authenticated users on the frontend if ( ! is_user_logged_in() ) { return; } // Support Center JS wp_enqueue_script( 'et-support-center', $this->local_path . 'admin/js/support-center.js', array( 'jquery', 'underscore' ), ET_CORE_VERSION, true ); $support_center_nonce = wp_create_nonce( 'support_center' ); $etSupportCenterSettings = array( 'ajaxLoaderImg' => esc_url( $this->local_path . 'admin/images/ajax-loader.gif' ), 'ajaxURL' => admin_url( 'admin-ajax.php' ), 'siteURL' => get_site_url(), 'supportCenterURL' => get_admin_url( null, 'admin.php?page=et_support_center#et_card_safe_mode' ), 'nonce' => $support_center_nonce, ); wp_localize_script( 'et-support-center', 'etSupportCenter', $etSupportCenterSettings ); } /** * Divi Support Center :: Card * * Take an array of attributes and build a WP Card block for display on the Divi Support Center page. * * @since 4.4.7 Added optional dismissible button * @since 3.20 * * @param array $attrs * * @return string */ protected function add_support_center_card( $attrs = array( 'title' => '', 'content' => '' ) ) { $card_classes = array( 'card', ); if ( array_key_exists( 'additional_classes', $attrs ) ) { $card_classes = array_merge( $card_classes, $attrs['additional_classes'] ); } $dismiss_button = ''; if ( array_key_exists( 'dismiss_button', $attrs ) ) { // Update card class to indicate the presence of the dismiss button $card_classes = array_merge( $card_classes, array( 'has-dismiss-button' ) ); // Prepare Class for the Dismiss button $dismiss_button_classes = array( 'et-dismiss-button' ); if ( array_key_exists( 'additional_classes', $attrs['dismiss_button'] ) ) { $dismiss_button_classes = array_merge( $dismiss_button_classes, $attrs['dismiss_button']['additional_classes'] ); } // Whether to display tooltip for the dismiss button $dismiss_button_has_tooltip = array_key_exists( 'tooltip', $attrs['dismiss_button'] ); // HTML Template for the dismiss button $dismiss_button = PHP_EOL . "\t" . sprintf( '', esc_html__( 'Dismiss', 'et-core' ), esc_attr( implode( ' ', $dismiss_button_classes ) ), esc_attr( $attrs['dismiss_button']['card_key'] ), esc_attr( $this->parent ), $dismiss_button_has_tooltip ? 'data-tippy-content="' . esc_attr( $attrs['dismiss_button']['tooltip'] ) . '"' : '' ); } $card = PHP_EOL . '
' . PHP_EOL . "\t" . '

' . esc_html( $attrs['title'] ) . '

' . PHP_EOL . "\t" . '
' . et_core_intentionally_unescaped( $attrs['content'], 'html' ) . '
' . et_core_esc_previously( $dismiss_button ) . PHP_EOL . '
'; return $card; } /** * Divi Support Center :: Dismiss a Card via Ajax * * @since 4.4.7 */ public function dismiss_support_center_card_via_ajax() { et_core_security_check( 'manage_options', 'support_center', 'nonce' ); $response = array(); // Check the ET product that dismissing the card $et_product = sanitize_key( $_POST['product'] ); // Confirm that this is a allowlisted product $allowlisted_product = $this->is_allowlisted_product( $et_product ); if ( ! $allowlisted_product ) { // Send a failure code and exit the function header( "HTTP/1.0 403 Forbidden" ); print 'Bad or malformed ET product name.'; wp_die(); } // Check the Card key against Cards that has a dismiss button $card_key = sanitize_key( $_POST['card_key'] ); if ( ! in_array( $card_key, $this->card_with_dismiss_button, true ) ) { // Send a failure code and exit the function header( "HTTP/1.0 403 Forbidden" ); print 'Card does not exists.'; wp_die(); } // Update option(s) update_option( "{$card_key}_dismissed", true ); // For Divi Hosting Card, update the status via ET API if ( $card_key === 'et_hosting_card' ) { $settings = $this->get_et_api_request_settings( 'disable_hosting_card' ); $et_username = et_()->array_get( $settings, 'body.username', '' ); $et_api_key = et_()->array_get( $settings, 'body.api_key', '' ); // Exit if ET Username and/or ET API Key is not found if ( $et_username === '' || $et_api_key === '' ) { return; } et_maybe_update_hosting_card_status(); } $response['message'] = sprintf( esc_html__( 'Card (%1$s) has been dismissed successfully.', 'et-core' ), $card_key ); // `echo` data to return if ( isset( $response ) ) { wp_send_json_success( $response ); } // `die` when we're done wp_die(); } /** * Prepare the "Divi Documentation & Help" video player block * * @since 3.28 Added support for Bloom, Monarch, and Divi Builer plugins. * @since 3.20 * * @param bool $formatted Return either a formatted HTML block (true) or an array (false) * * @return array|string */ protected function get_documentation_video_player( $formatted = true ) { /** * Define the videos list */ switch ( $this->parent ) { case 'extra_theme': $documentation_videos = array( array( 'name' => esc_attr__( 'A Basic Overview Of Extra', 'et-core' ), 'youtube_id' => 'JDSg9eq4LIc', ), array( 'name' => esc_attr__( 'Using Premade Layout Packs', 'et-core' ), 'youtube_id' => '9eqXcrLcnoc', ), array( 'name' => esc_attr__( 'Creating Category Layouts', 'et-core' ), 'youtube_id' => '30SVxnjdnxcE', ), ); break; case 'divi_theme': case 'divi_builder_plugin': $documentation_videos = array( array( 'name' => esc_attr__( 'Getting Started With The Divi Builder', 'et-core' ), 'youtube_id' => 'T-Oe01_J62c', ), array( 'name' => esc_attr__( 'Using Premade Layout Packs', 'et-core' ), 'youtube_id' => '9eqXcrLcnoc', ), array( 'name' => esc_attr__( 'The Divi Library', 'et-core' ), 'youtube_id' => 'boNZZ0MYU0E', ), ); break; case 'bloom_plugin': $documentation_videos = array( array( 'name' => esc_attr__( 'A Basic Overview Of The Bloom Plugin', 'et-core' ), 'youtube_id' => 'E4nfXFjuRRI', ), array( 'name' => esc_attr__( 'How To Update The Bloom Plugin', 'et-core' ), 'youtube_id' => '-IIdkRLskuA', ), array( 'name' => esc_attr__( 'How To Add Mailing List Accounts', 'et-core' ), 'youtube_id' => 'nEdWkHIgQwY', ), ); break; case 'monarch_plugin': $documentation_videos = array( array( 'name' => esc_attr__( 'A Complete Overviw Of Monarch', 'et-core' ), 'youtube_id' => 'RlMUEVkbMrs', ), array( 'name' => esc_attr__( 'Adding Social Networks', 'et-core' ), 'youtube_id' => 'ZabKCiKQJLM', ), array( 'name' => esc_attr__( 'Configuring Social Follower APIs', 'et-core' ), 'youtube_id' => 'vmE8uFhbzos', ), ); break; default: $documentation_videos = array(); } // If we just want the array (not a formatted HTML block), return that now if ( false === $formatted ) { return $documentation_videos; } $videos_list_html = ''; $playlist = array(); foreach ( $documentation_videos as $key => $video ) { $extra = ''; if ( 0 === $key ) { $extra = ' class="active"'; } $videos_list_html .= sprintf( '
  • %3$s%4$s
  • ', $extra, esc_attr( $video['youtube_id'] ), '', et_core_intentionally_unescaped( $video['name'], 'fixed_string' ) ); $playlist[] = et_core_intentionally_unescaped( $video['youtube_id'], 'fixed_string' ); } $html = sprintf( '
    ' . '
    ' . '
      %2$s
    ' . '
    ', esc_attr( implode( ',', $playlist ) ), $videos_list_html ); return $html; } /** * Prepare the "Divi Documentation & Help" articles list * * @since 3.28 Added support for Bloom, Monarch, and Divi Builer plugins. * @since 3.20 * * @param bool $formatted Return either a formatted HTML block (true) or an array (false) * * @return array|string */ protected function get_documentation_articles_list( $formatted = true ) { $articles_list_html = ''; switch ( $this->parent ) { case 'extra_theme': $articles = array( array( 'title' => esc_attr__( 'Getting Started With Extra', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/extra/overview-extra/', ), array( 'title' => esc_attr__( 'Setting Up The Extra Theme Options', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/extra/theme-options-extra/', ), array( 'title' => esc_attr__( 'The Extra Category Builder', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/extra/category-builder/', ), array( 'title' => esc_attr__( 'Getting Started With The Divi Builder', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/visual-builder/', ), array( 'title' => esc_attr__( 'How To Update The Extra Theme', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/update-divi/', ), array( 'title' => esc_attr__( 'An Overview Of All Divi Modules', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/modules/', ), array( 'title' => esc_attr__( 'Getting Started With Layout Packs', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/premade-layouts/', ), array( 'title' => esc_attr__( 'Customizing Your Header And Navigation', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/extra/theme-customizer/', ), ); break; case 'divi_theme': $articles = array( array( 'title' => esc_attr__( 'Getting Started With The Divi Builder', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/visual-builder/', ), array( 'title' => esc_attr__( 'How To Update The Divi Theme', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/update-divi/', ), array( 'title' => esc_attr__( 'An Overview Of All Divi Modules', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/modules/', ), array( 'title' => esc_attr__( 'Using The Divi Library', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/divi-library/', ), array( 'title' => esc_attr__( 'Setting Up The Divi Theme Options', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/theme-options/', ), array( 'title' => esc_attr__( 'Getting Started With Layout Packs', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/premade-layouts/', ), array( 'title' => esc_attr__( 'Customizing Your Header And Navigation', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/customizer-header/', ), array( 'title' => esc_attr__( 'Divi For Developers', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/developers/', ), ); break; case 'divi_builder_plugin': $articles = array( array( 'title' => esc_attr__( 'Getting Started With The Divi Builder', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/visual-builder/', ), array( 'title' => esc_attr__( 'How To Update The Divi Builder', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi-builder/update-divi-builder/', ), array( 'title' => esc_attr__( 'An Overview Of All Divi Modules', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/modules/', ), array( 'title' => esc_attr__( 'Using The Divi Library', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/divi-library/', ), array( 'title' => esc_attr__( 'Selling Products With Divi And WooCommerce', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/ecommerce-divi/', ), array( 'title' => esc_attr__( 'Getting Started With Layout Packs', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/premade-layouts/', ), array( 'title' => esc_attr__( 'Importing And Exporting Divi Layouts', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/divi/library-import/', ), array( 'title' => esc_attr__( 'Divi For Developers', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/developers/', ), ); break; case 'bloom_plugin': $articles = array( array( 'title' => esc_attr__( 'A Basic Overview Of The Bloom Plugin', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/overview/', ), array( 'title' => esc_attr__( 'How To Update Your Bloom Plugin', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/update/', ), array( 'title' => esc_attr__( 'Adding Email Accounts In Bloom', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/accounts/', ), array( 'title' => esc_attr__( 'Customizing Your Opt-in Designs', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/design/', ), array( 'title' => esc_attr__( 'The Different Bloom Opt-in Types', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/optin-types/', ), array( 'title' => esc_attr__( 'Using The Bloom Display Settings', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/display/', ), array( 'title' => esc_attr__( 'How To Use Triggers In Bloom', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/triggers/', ), array( 'title' => esc_attr__( 'Adding Custom Fields To Bloom Opt-in Forms', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/bloom/optin/adding-custom-fields-to-bloom-optin-forms/', ), ); break; case 'monarch_plugin': $articles = array( array( 'title' => esc_attr__( 'A Complete Overview Of The Monarch Plugin', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/overview-monarch/', ), array( 'title' => esc_attr__( 'How To Update Your Monarch WordPress Plugin', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/update-monarch/', ), array( 'title' => esc_attr__( 'Adding and Managing Social Networks', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/networks/', ), array( 'title' => esc_attr__( 'Configuring Social Network APIs', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/api/', ), array( 'title' => esc_attr__( 'Customizing The Monarch Design', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/design-monarch/', ), array( 'title' => esc_attr__( 'Viewing Your Social Stats', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/stats/', ), array( 'title' => esc_attr__( 'Using The Floating Sidebar', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/sidebar/', ), array( 'title' => esc_attr__( 'Using Popup & Flyin Triggers', 'et-core' ), 'url' => 'https://www.elegantthemes.com/documentation/monarch/triggers-monarch/', ), ); break; default: $articles = array(); } // If we just want the array (not a formatted HTML block), return that now if ( false === $formatted ) { return $articles; } foreach ( $articles as $key => $article ) { $articles_list_html .= sprintf( '
  • %2$s
  • ', esc_url( $article['url'] ), et_core_intentionally_unescaped( $article['title'], 'fixed_string' ) ); } $html = sprintf( '
      %1$s
    ', $articles_list_html ); return $html; } /** * Look for Elegant Themes Support Account * * @since 3.20 * * @return WP_User|false WP_User object on success, false on failure. */ public function get_et_support_user() { return get_user_by( 'slug', $this->support_user_account_name ); } /** * Look for saved Elegant Themes Username & API Key * * @since 3.20 * * @return array|false license credentials on success, false on failure. */ public function get_et_license() { /** @var array License credentials [username|api_key] */ if ( ! $et_license = get_site_option( 'et_automatic_updates_options' ) ) { $et_license = get_option( 'et_automatic_updates_options', array() ); } if ( ! et_()->array_get( $et_license, 'username' ) ) { return false; } if ( ! et_()->array_get( $et_license, 'api_key' ) ) { return false; } return $et_license; } /** * Try to load the WP debug log. If found, return the last [$lines_to_return] lines of the file and the filesize. * * @since 3.20 * * @param int $lines_to_return Number of lines to read and return from the end of the wp_debug.log file. * * @return array */ protected function get_wp_debug_log( $lines_to_return = 10 ) { $log = array( 'entries' => '', 'size' => 0, ); // Early exit: internal PHP function `file_get_contents()` appears to be on lockdown if ( ! function_exists( 'file_get_contents' ) ) { $log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug log cannot be read.', 'et-core' ); if ( defined( 'ET_DEBUG' ) ) { et_error( $log['error'] ); } return $log; } // Early exit: WP_DEBUG_LOG isn't defined in wp-config.php (or it's defined, but it's empty) if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) { $log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug.log is not configured.', 'et-core' ); if ( defined( 'ET_DEBUG' ) ) { et_error( $log['error'] ); } return $log; } /** * WordPress 5.1 introduces the option to define a custom path for the WP_DEBUG_LOG file. * * @see wp_debug_mode() * * @since 3.20 */ if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) { $wp_debug_log_path = realpath( WP_CONTENT_DIR . '/debug.log' ); } else if ( is_string( WP_DEBUG_LOG ) ) { $wp_debug_log_path = realpath( WP_DEBUG_LOG ); } // Early exit: `debug.log` doesn't exist or otherwise can't be read if ( ! isset( $wp_debug_log_path ) || ! file_exists( $wp_debug_log_path ) || ! is_readable( $wp_debug_log_path ) ) { $log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug log cannot be found.', 'et-core' ); if ( defined( 'ET_DEBUG' ) ) { et_error( $log['error'] ); } return $log; } /** * At this point, we know: * (1) `$wp_debug_log_path` is set, * (2) it points to a valid location, and * (3) what it points to is readable. * * Before we continue, we'll ensure `$wp_debug_log_path` does not point to a directory. */ // Early exit: debug log definition points to a directory, not a file. if ( is_dir( $wp_debug_log_path ) ) { $log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug log setting points to a directory, but should point to a file.', 'et-core' ); if ( defined( 'ET_DEBUG' ) ) { et_error( $log['error'] ); } return $log; } // Load the debug.log file $file = new SplFileObject( $wp_debug_log_path ); // Get the filesize of debug.log $log['size'] = $this->get_size_in_shorthand( 0 + $file->getSize() ); // If $lines_to_return is a positive integer, fetch the last [$lines_to_return] lines of the log file $lines_to_return = (int) $lines_to_return; if ( $lines_to_return > 0 ) { $file->seek( PHP_INT_MAX ); $total_lines = $file->key(); // If the file is smaller than the number of lines requested, return the entire file. $reader = new LimitIterator( $file, max( 0, $total_lines - $lines_to_return ) ); $log['entries'] = ''; foreach ( $reader as $line ) { $log['entries'] .= $line; } } // Unload the SplFileObject $file = null; return $log; } /** * When a predefined system setting is passed to this function, it will return the observed value. * * @since 3.20 * * @param bool $formatted Whether to return a formatted report or just the data array * @param string $format Return the report as either a `div` or `plain` text (if $formatted = true) * * @return array|string */ protected function system_diagnostics_generate_report( $formatted = true, $format = 'plain' ) { /** @var array Collection of system settings to run diagnostic checks on. */ global $wp_version; global $shortname; $divi_builder_plugin_active = et_is_builder_plugin_active(); if ( $divi_builder_plugin_active ) { $options = get_option( 'et_pb_builder_options', array() ); } if ( 'divi' === $shortname ) { $performance_options_url = get_admin_url() . 'admin.php?page=et_divi_options#general-2'; $builder_options_url = get_admin_url() . 'admin.php?page=et_divi_options#builder-2'; } elseif ( 'extra' === $shortname ) { $performance_options_url = get_admin_url() . 'admin.php?page=et_extra_options#general-2'; $builder_options_url = get_admin_url() . 'admin.php?page=et_extra_options#builder-2'; } else { $performance_options_url = get_admin_url() . 'admin.php?page=et_divi_options#tab_et_dashboard_tab_content_performance_main'; $builder_options_url = get_admin_url() . 'admin.php?page=et_divi_options#tab_et_dashboard_tab_content_advanced_main'; } $system_diagnostics_settings = array( array( 'name' => esc_attr__( 'Writable wp-content Directory', 'et-core' ), 'environment' => 'server', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'minimum' => null, 'recommended' => true, 'actual' => wp_is_writable( WP_CONTENT_DIR ), 'help_text' => et_core_intentionally_unescaped( __( 'We recommend that the wp-content directory on your server be writable by WordPress in order to ensure the full functionality of Divi Builder themes and plugins.', 'et-core' ), 'html' ), 'learn_more' => 'https://wordpress.org/support/article/changing-file-permissions/', ), array( 'name' => esc_attr__( 'Writable et-cache Directory', 'et-core' ), 'environment' => 'server', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'minimum' => null, 'recommended' => true, 'actual' => wp_is_writable( WP_CONTENT_DIR . '/et-cache' ), 'help_text' => et_core_intentionally_unescaped( __( 'We recommend that the et-cache directory on your server be writable by WordPress in order to ensure the full functionality of Divi Builder themes and plugins.', 'et-core' ), 'html' ), 'learn_more' => 'https://wordpress.org/support/article/changing-file-permissions/', ), array( 'name' => esc_attr__( 'PHP: Version', 'et-core' ), 'environment' => 'server', 'type' => 'version', 'pass_minus_one' => false, 'pass_zero' => false, 'minimum' => null, 'recommended' => '7.4 or higher', 'actual' => (float) phpversion(), 'help_text' => et_core_intentionally_unescaped( __( 'We recommend using the latest stable version of PHP. This will not only ensure compatibility with Divi, but it will also greatly speed up your website leading to less memory and CPU related issues.', 'et-core' ), 'html' ), 'learn_more' => 'http://php.net/releases/', ), array( 'name' => esc_attr__( 'WordPress Version', 'et-core' ), 'environment' => 'server', 'type' => 'version', 'pass_minus_one' => false, 'pass_zero' => false, 'minimum' => null, 'recommended' => '5.3 or higher', 'actual' => $wp_version, 'help_text' => et_core_intentionally_unescaped( __( 'We recommend using the latest stable version of WordPress. This will not only ensure compatibility with Divi, but it will also greatly speed up your website leading to less memory and CPU related issues.', 'et-core' ), 'html' ), 'learn_more' => 'https://wordpress.org/download/releases/', ), array( 'name' => esc_attr__( 'PHP: memory_limit', 'et-core' ), 'environment' => 'server', 'type' => 'size', 'pass_minus_one' => true, 'pass_zero' => false, 'minimum' => null, 'recommended' => '128M', 'actual' => ini_get( 'memory_limit' ), 'help_text' => et_get_safe_localization( sprintf( __( 'By default, memory limits set by your host or by WordPress may be too low. This will lead to applications crashing as PHP reaches the artificial limit. You can adjust your memory limit within your php.ini file, or by contacting your host for assistance. You may also need to define a memory limited in wp-config.php.', 'et-core' ), 'http://php.net/manual/en/ini.core.php#ini.memory-limit', 'https://codex.wordpress.org/Editing_wp-config.php' ) ), 'learn_more' => 'http://php.net/manual/en/ini.core.php#ini.memory-limit', ), array( 'name' => esc_attr__( 'PHP: post_max_size', 'et-core' ), 'environment' => 'server', 'type' => 'size', 'pass_minus_one' => false, 'pass_zero' => true, 'minimum' => null, 'recommended' => '64M', 'actual' => ini_get( 'post_max_size' ), 'help_text' => et_get_safe_localization( sprintf( __( 'Post Max Size limits how large a page or file can be on your website. If your page is larger than the limit set in PHP, it will fail to load. Post sizes can become quite large when using the Divi Builder, so it is important to increase this limit. It also affects file size upload/download, which can prevent large layouts from being imported into the builder. You can adjust your max post size within your php.ini file, or by contacting your host for assistance.', 'et_core' ), 'http://php.net/manual/en/ini.core.php#ini.post-max-size' ) ), 'learn_more' => 'http://php.net/manual/en/ini.core.php#ini.post-max-size', ), array( 'name' => esc_attr__( 'PHP: max_execution_time', 'et-core' ), 'environment' => 'server', 'type' => 'seconds', 'pass_minus_one' => false, 'pass_zero' => true, 'minimum' => null, 'recommended' => '120', 'actual' => ini_get( 'max_execution_time' ), 'help_text' => et_get_safe_localization( sprintf( __( 'Max Execution Time affects how long a page is allowed to load before it times out. If the limit is too low, you may not be able to import large layouts and files into the builder. You can adjust your max execution time within your php.ini file, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/info.configuration.php#ini.max-execution-time' ) ), 'learn_more' => 'http://php.net/manual/en/info.configuration.php#ini.max-execution-time', ), array( 'name' => esc_attr__( 'PHP: upload_max_filesize', 'et-core' ), 'environment' => 'server', 'type' => 'size', 'pass_minus_one' => false, 'pass_zero' => true, 'minimum' => null, 'recommended' => '64M', 'actual' => ini_get( 'upload_max_filesize' ), 'help_text' => et_get_safe_localization( sprintf( __( 'Upload Max File Size determines that maximum file size that you are allowed to upload to your server. If the limit is too low, you may not be able to import large collections of layouts into the Divi Library. You can adjust your max file size within your php.ini file, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/ini.core.php#ini.upload-max-filesize' ) ), 'learn_more' => 'http://php.net/manual/en/ini.core.php#ini.upload-max-filesize', ), array( 'name' => esc_attr__( 'PHP: max_input_time', 'et-core' ), 'environment' => 'server', 'type' => 'seconds', 'pass_minus_one' => true, 'pass_zero' => true, 'minimum' => null, 'recommended' => '60', 'actual' => ini_get( 'max_input_time' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This sets the maximum time in seconds a script is allowed to parse input data. If the limit is too low, the Divi Builder may time out before it is allowed to load. You can adjust your max input time within your php.ini file, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/info.configuration.php#ini.max-input-time' ) ), 'learn_more' => 'http://php.net/manual/en/info.configuration.php#ini.max-input-time', ), array( 'name' => esc_attr__( 'PHP: max_input_vars', 'et-core' ), 'environment' => 'server', 'type' => 'size', 'pass_minus_one' => false, 'pass_zero' => false, 'minimum' => null, 'recommended' => '1000', 'actual' => ini_get( 'max_input_vars' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This setting affects how many input variables may be accepted. If the limit is too low, it may prevent the Divi Builder from loading. You can adjust your max input variables within your php.ini file, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/info.configuration.php#ini.max-input-vars' ) ), 'learn_more' => 'http://php.net/manual/en/info.configuration.php#ini.max-input-vars', ), array( 'name' => esc_attr__( 'PHP: display_errors', 'et-core' ), 'environment' => 'server', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'pass_exact' => null, 'minimum' => null, 'recommended' => '0', 'actual' => ! ini_get( 'display_errors' ) ? '0' : ini_get( 'display_errors' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This setting determines whether or not errors should be printed as part of the page output. This is a feature to support your site\'s development and should never be used on production sites. You can edit this setting within your php.ini file, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors' ) ), 'learn_more' => 'http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors', ), array( 'name' => esc_attr__( 'Dynamic CSS', 'et-core' ), 'environment' => 'performance', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'pass_exact' => null, 'minimum' => null, 'recommended' => 'on', 'actual' => $divi_builder_plugin_active ? ( isset( $options['performance_main_dynamic_css'] ) ? $options['performance_main_dynamic_css'] : 'on' ) : et_get_option( $shortname . '_dynamic_css', 'on' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This is a very important performance setting that should be turned on. Dynamic CSS greatly reduces your website\'s CSS size, speeds up page load times and improves Google PageSpeed scores. You can turn this setting on in the Theme Options.', 'et-core' ), $performance_options_url ) ), 'learn_more' => $performance_options_url, ), array( 'name' => esc_attr__( 'Dynamic Framework', 'et-core' ), 'environment' => 'performance', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'pass_exact' => null, 'minimum' => null, 'recommended' => 'on', 'actual' => $divi_builder_plugin_active ? ( isset( $options['performance_main_dynamic_module_framework'] ) ? $options['performance_main_dynamic_module_framework'] : 'on' ) : et_get_option( $shortname . '_dynamic_module_framework', 'on' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This is a very important performance setting that should be turned on. The Dynamic Framework removes bloat from the back-end. This greatly reduces CPU and Memory usage and improves website speed. You can turn this setting on in the Theme Options.', 'et-core' ), $performance_options_url ) ), 'learn_more' => $performance_options_url, ), array( 'name' => esc_attr__( 'Dynamic JavaScript', 'et-core' ), 'environment' => 'performance', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'pass_exact' => null, 'minimum' => null, 'recommended' => 'on', 'actual' => $divi_builder_plugin_active ? ( isset( $options['performance_main_dynamic_css'] ) ? $options['performance_main_dynamic_css'] : 'on' ) : et_get_option( $shortname . '_dynamic_js_libraries', 'on' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This is a very important performance setting that should be turned on. Dynamic JavaScript removes unused scripts and improves website speed by loading JavaScript files only when they are needed. You can turn this setting on in the Theme Options.', 'et-core' ), $performance_options_url ) ), 'learn_more' => $performance_options_url, ), array( 'name' => esc_attr__( 'Critical CSS', 'et-core' ), 'environment' => 'performance', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'pass_exact' => null, 'minimum' => null, 'recommended' => 'on', 'actual' => $divi_builder_plugin_active ? ( isset( $options['performance_main_critical_css'] ) ? $options['performance_main_dynamic_css'] : 'on' ) : et_get_option( $shortname . '_critical_css', 'on' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This is a very important performance setting that should be turned on. Critical CSS greatly improves website loading speeds by deferring "below the fold" styles and removing render blocking requests for critical styles. You can turn this setting on in the Theme Options.', 'et-core' ), $performance_options_url ) ), 'learn_more' => $performance_options_url, ), array( 'name' => esc_attr__( 'Static CSS', 'et-core' ), 'environment' => 'performance', 'type' => 'truthy_falsy', 'pass_minus_one' => null, 'pass_zero' => null, 'pass_exact' => null, 'minimum' => null, 'recommended' => 'on', 'actual' => et_get_option( 'et_pb_static_css_file', 'on' ), 'help_text' => et_get_safe_localization( sprintf( __( 'This is a very important performance setting that should be turned on, even if you are using a caching plugin. Static CSS caches the builder CSS for each page so that it doesn\'t need to be processed on every page load. Even if you are using a caching plugin, this setting should still be turned on so that dynamic pages benefit. You can turn this setting on in the Theme Options.', 'et-core' ), $builder_options_url ) ), 'learn_more' => $builder_options_url, ), ); /** @var string Formatted report. */ $report = ''; // pass/fail Should be one of pass|minimal|fail|unknown. Defaults to 'unknown'. foreach ( $system_diagnostics_settings as $i => $scan ) { /** * 'pass_fail': four-step process to set its value: * - begin with `unknown` state; * - if recommended value exists, change to `fail`; * - if minimum value exists, compare against it & change to `minimal` if it passes; * - compare against recommended value & change to `pass` if it passes. */ $system_diagnostics_settings[ $i ]['pass_fail'] = 'unknown'; if ( ! is_null( $scan['recommended'] ) ) { $system_diagnostics_settings[ $i ]['pass_fail'] = 'fail'; } if ( ! is_null( $scan['minimum'] ) && $this->value_is_at_least( $scan['minimum'], $scan['actual'], $scan['type'] ) ) { $system_diagnostics_settings[ $i ]['pass_fail'] = 'minimal'; } if ( empty( $scan['pass_exact'] ) && ! is_null( $scan['recommended'] ) && $this->value_is_at_least( $scan['recommended'], $scan['actual'], $scan['type'] ) ) { $system_diagnostics_settings[ $i ]['pass_fail'] = 'pass'; } if ( $scan['pass_minus_one'] && -1 === (int) $scan['actual'] ) { $system_diagnostics_settings[ $i ]['pass_fail'] = 'pass'; } if ( $scan['pass_zero'] && 0 === (int) $scan['actual'] ) { $system_diagnostics_settings[ $i ]['pass_fail'] = 'pass'; } if ( ! empty( $scan['pass_exact'] ) && $scan['recommended'] === $scan['actual'] ) { $system_diagnostics_settings[ $i ]['pass_fail'] = 'pass'; } /** * Build messaging for minimum required values */ $message_minimum = ''; if ( ! is_null( $scan['minimum'] ) && 'fail' === $system_diagnostics_settings[ $i ]['pass_fail'] ) { $message_minimum = sprintf( esc_html__( 'This fails to meet our minimum required value of %1$s. ', 'et-core' ), esc_html( is_bool( $scan['minimum'] ) ? $this->boolean_label[ $scan['minimum'] ] : $scan['minimum'] ) ); } if ( ! is_null( $scan['minimum'] ) && 'minimal' === $system_diagnostics_settings[ $i ]['pass_fail'] ) { $message_minimum = sprintf( esc_html__( 'This meets our minimum required value of %1$s. ', 'et-core' ), esc_html( is_bool( $scan['minimum'] ) ? $this->boolean_label[ $scan['minimum'] ] : $scan['minimum'] ) ); } /** * Build description messaging for results & recommendation */ $learn_more_link = ''; if ( ! is_null( $scan['learn_more'] ) ) { $learn_more_link = sprintf( ' %2$s', esc_url( $scan['learn_more'] ), esc_html__( 'server' === $scan['environment'] ? 'Learn More.' : 'Enable Option.', 'et-core' ) ); } switch ( $system_diagnostics_settings[ $i ]['pass_fail'] ) { case 'pass': $system_diagnostics_settings[ $i ]['description'] = sprintf( '- %1$s %2$s', sprintf( esc_html__( 'performance' === $scan['environment'] ? 'Perfect! We recommend enabling this option.' : 'Congratulations! This meets or exceeds our recommendation of %1$s.', 'et-core' ), esc_html( is_bool( $scan['recommended'] ) ? $this->boolean_label[ $scan['recommended'] ] : $scan['recommended'] ) ), et_core_intentionally_unescaped( $learn_more_link, 'html' ) ); break; case 'minimal': case 'fail': $system_diagnostics_settings[ $i ]['description'] = sprintf( '- %1$s%2$s %3$s', esc_html( $message_minimum ), sprintf( esc_html__( 'performance' === $scan['environment'] ? 'Enable for optimal performance.' : 'We recommend %1$s for the best experience.', 'et-core' ), esc_html( is_bool( $scan['recommended'] ) ? $this->boolean_label[ $scan['recommended'] ] : $scan['recommended'] ) ), et_core_intentionally_unescaped( $learn_more_link, 'html' ) ); break; case 'unknown': default: $system_diagnostics_settings[ $i ]['description'] = sprintf( esc_html__( '- We are unable to determine your setting. %1$s', 'et-core' ), et_core_intentionally_unescaped( $learn_more_link, 'html' ) ); } } // If we just want the array (not a formatted HTML block), return that now if ( false === $formatted ) { return $system_diagnostics_settings; } foreach ( $system_diagnostics_settings as $item ) { // Add reported setting to plaintext report: if ( 'plain' === $format ) { switch ( $item['pass_fail'] ) { case 'pass': $status = ' '; break; case 'minimal': $status = '~ '; break; case 'fail': $status = "! "; break; case 'unknown': default: $status = '? '; } $report .= $status . $item['name'] . PHP_EOL . ' ' . $item['actual'] . PHP_EOL . PHP_EOL; } // Add reported setting to table: if ( 'div' === $format ) { $help_text = ''; if ( ! is_null( $item['help_text'] ) ) { $help_text = $item['help_text']; } $report .= sprintf( '

    %2$s

    %3$s

    %4$s %5$s
    ', esc_attr( $item['pass_fail'] ), esc_html( $item['name'] ), et_core_intentionally_unescaped( $help_text, 'html' ), esc_html( is_bool( $item['actual'] ) ? $this->boolean_label[ $item['actual'] ] : $item['actual'] ), et_core_intentionally_unescaped( $item['description'], 'html' ) ); } } // Prepend title and timestamp if ( 'plain' === $format ) { $report = '## ' . esc_html__( 'System Status', 'et-core' ) . ' ##' . PHP_EOL . ':: ' . date( 'Y-m-d @ H:i:s e' ) . PHP_EOL . PHP_EOL . $report; } if ( 'div' === $format ) { $report = sprintf( '
    %1$s

    %2$s

    ', $report, esc_html__( 'Congratulations, all system checks have passed. Your hosting configuration is compatible with Divi.', 'et-core' ), 'et-system-status' ); } return $report; } /** * Convert size string with "shorthand byte" notation to raw byte value for comparisons. * * @since 3.20 * * @param string $size * * @return int size in bytes */ protected function get_size_in_bytes( $size = '' ) { // Capture the denomination and convert to uppercase, then do math to it switch ( strtoupper( substr( $size, -1 ) ) ) { // Terabytes case 'T': return (int) $size * 1099511627776; // Gigabytes case 'G': return (int) $size * 1073741824; // Megabytes case 'M': return (int) $size * 1048576; // Kilobytes case 'K': return (int) $size * 1024; default: return (int) $size; } } /** * Convert size string with "shorthand byte" notation to raw byte value for comparisons. * * @since 3.20 * * @param int $bytes * @param int $precision * * @return string size in "shorthand byte" notation */ protected function get_size_in_shorthand( $bytes = 0, $precision = 2 ) { $units = array( ' bytes', 'KB', 'MB', 'GB', 'TB' ); $i = 0; while ( $bytes > 1024 ) { $bytes /= 1024; $i++; } return round( $bytes, $precision ) . $units[ $i ]; } /** * Size comparisons between two values using a variety of calculation methods. * * @since 3.20.2 * * @param string|int|float $a Our value to compare against * @param string|int|float $b Server value being compared * @param string $type Comparison type * * @return bool Whether the second value is equal to or greater than the first */ protected function value_is_at_least( $a, $b, $type = 'size' ) { switch ( $type ) { case 'truthy_falsy': return $this->value_is_falsy( $a ) === $this->value_is_falsy( $b ); case 'version': return (float) $a <= (float) $b; case 'seconds': return (int) $a <= (int) $b; case 'size': default: return $this->get_size_in_bytes( $a ) <= $this->get_size_in_bytes( $b ); } } /** * Check value against a collection of "falsy" values * * @since 3.23 * * @param string|int|float $a Value to compare against * * @return bool Whether the second value is equal to or greater than the first */ protected function value_is_falsy( $a ) { // Accept falsy strings regardless of case (e.g. 'off', 'Off', 'OFF', 'oFf') if ( is_string( $a ) ) { $a = strtolower( $a ); } return in_array( $a, array( false, 'false', 0, '0', 'off' ), true ); } /** * SUPPORT CENTER :: REMOTE ACCESS */ /** * Add Support Center options to the Role Editor screen * * @see ET_Core_SupportCenter::current_user_can() * * @since 3.20 * * @param $all_role_options * * @return array */ public function support_user_add_role_options( $all_role_options ) { // get all the roles that can edit theme options. $applicability_roles = et_core_get_roles_by_capabilities( [ 'edit_theme_options' ] ); $all_role_options['support_center'] = array( 'section_title' => esc_attr__( 'Support Center', 'et-core' ), 'applicability' => $applicability_roles, 'options' => array( 'et_support_center' => array( 'name' => esc_attr__( 'Divi Support Center Page', 'et-core' ), ), 'et_support_center_system' => array( 'name' => esc_attr__( 'System Status', 'et-core' ), ), 'et_support_center_remote_access' => array( 'name' => esc_attr__( 'Remote Access', 'et-core' ), ), 'et_support_center_documentation' => array( 'name' => esc_attr__( 'Divi Documentation & Help', 'et-core' ), ), 'et_support_center_safe_mode' => array( 'name' => esc_attr__( 'Safe Mode', 'et-core' ), ), 'et_support_center_logs' => array( 'name' => esc_attr__( 'Logs', 'et-core' ), ), ), ); return $all_role_options; } /** * Add third party capabilities to Remote Access roles * * @return array Capabilities to add to the Remote Access user roles. */ public function support_user_extra_caps_standard( $extra_capabilities = array() ) { // The Events Calendar (if active on the site) if ( class_exists( 'Tribe__Events__Main' ) ) { $the_events_calendar = array( // Events 'edit_tribe_event' => 1, 'read_tribe_event' => 1, 'delete_tribe_event' => 1, 'delete_tribe_events' => 1, 'edit_tribe_events' => 1, 'edit_others_tribe_events' => 1, 'delete_others_tribe_events' => 1, 'publish_tribe_events' => 1, 'edit_published_tribe_events' => 1, 'delete_published_tribe_events' => 1, 'delete_private_tribe_events' => 1, 'edit_private_tribe_events' => 1, 'read_private_tribe_events' => 1, // Venues 'edit_tribe_venue' => 1, 'read_tribe_venue' => 1, 'delete_tribe_venue' => 1, 'delete_tribe_venues' => 1, 'edit_tribe_venues' => 1, 'edit_others_tribe_venues' => 1, 'delete_others_tribe_venues' => 1, 'publish_tribe_venues' => 1, 'edit_published_tribe_venues' => 1, 'delete_published_tribe_venues' => 1, 'delete_private_tribe_venues' => 1, 'edit_private_tribe_venues' => 1, 'read_private_tribe_venues' => 1, // Organizers 'edit_tribe_organizer' => 1, 'read_tribe_organizer' => 1, 'delete_tribe_organizer' => 1, 'delete_tribe_organizers' => 1, 'edit_tribe_organizers' => 1, 'edit_others_tribe_organizers' => 1, 'delete_others_tribe_organizers' => 1, 'publish_tribe_organizers' => 1, 'edit_published_tribe_organizers' => 1, 'delete_published_tribe_organizers' => 1, 'delete_private_tribe_organizers' => 1, 'edit_private_tribe_organizers' => 1, 'read_private_tribe_organizers' => 1, ); $extra_capabilities = array_merge( $extra_capabilities, $the_events_calendar ); } return $extra_capabilities; } /** * Add third party capabilities to the *Elevated* Remote Access role only * * @return array Capabilities to add to the Elevated Remote Access user role. */ public function support_user_extra_caps_elevated() { $extra_capabilities = array(); return $extra_capabilities; } /** * Create the Divi Support user (if it doesn't already exist) * * @since 3.20 * * @return void|WP_Error */ public function support_user_maybe_create_user() { if ( username_exists( $this->support_user_account_name ) ) { return; } // Define user roles that will be used to control ET Support User permissions $this->support_user_create_roles(); $token = $this->support_user_generate_token(); $password = $this->support_user_generate_password( $token ); if ( is_wp_error( $password ) ) { return $password; } $user_id = wp_insert_user( array( 'user_login' => $this->support_user_account_name, 'user_pass' => $password, 'first_name' => 'Elegant Themes', 'last_name' => 'Support', 'display_name' => 'Elegant Themes Support', 'role' => 'et_support', ) ); if ( is_wp_error( $user_id ) ) { return $user_id; } $account_settings = array( 'date_created' => time(), 'token' => $token, ); update_option( $this->support_user_options_name, $account_settings ); // update options variable $this->support_user_get_options(); $this->support_user_init_cron_delete_account(); } /** * Define both Standard and Elevated roles for the Divi Support user * * @since 3.22 Added filters to extend the list of capabilities for the ET Support User * @since 3.20 */ public function support_user_create_roles() { // Make sure old versions of these roles do not exist $this->support_user_remove_roles(); // Divi Support :: Standard $standard_capabilities = array( 'assign_product_terms' => true, 'delete_pages' => true, 'delete_posts' => true, 'delete_private_pages' => true, 'delete_private_posts' => true, 'delete_private_products' => true, 'delete_product' => true, 'delete_product_terms' => true, 'delete_products' => true, 'delete_published_pages' => true, 'delete_published_posts' => true, 'delete_published_products' => true, 'edit_dashboard' => true, 'edit_files' => true, 'edit_others_pages' => true, 'edit_others_posts' => true, 'edit_others_products' => true, 'edit_pages' => true, 'edit_posts' => true, 'edit_private_pages' => true, 'edit_private_posts' => true, 'edit_private_products' => true, 'edit_product' => true, 'edit_product_terms' => true, 'edit_products' => true, 'edit_published_pages' => true, 'edit_published_posts' => true, 'edit_published_products' => true, 'edit_theme_options' => true, 'list_users' => true, 'manage_categories' => true, 'manage_links' => true, 'manage_options' => true, 'manage_product_terms' => true, 'moderate_comments' => true, 'publish_pages' => true, 'publish_posts' => true, 'publish_products' => true, 'read' => true, 'read_private_pages' => true, 'read_private_posts' => true, 'read_private_products' => true, 'read_product' => true, 'unfiltered_html' => true, 'upload_files' => true, // Divi 'ab_testing' => true, 'add_library' => true, 'disable_module' => true, 'divi_builder_control' => true, 'divi_ai' => true, 'divi_library' => true, 'edit_borders' => true, 'edit_buttons' => true, 'edit_colors' => true, 'edit_configuration' => true, 'edit_content' => true, 'edit_global_library' => true, 'edit_layout' => true, 'export' => true, 'lock_module' => true, 'page_options' => true, 'portability' => true, 'read_dynamic_content_custom_fields' => true, 'save_library' => true, 'use_visual_builder' => true, 'theme_builder' => true, // WooCommerce Capabilities 'manage_woocommerce' => true, ); // Divi Support :: Elevated $elevated_capabilities = array_merge( $standard_capabilities, array( 'activate_plugins' => true, 'delete_plugins' => true, 'delete_themes' => true, 'edit_plugins' => true, 'edit_themes' => true, 'install_plugins' => true, 'install_themes' => true, 'switch_themes' => true, 'update_plugins' => true, 'update_themes' => true, ) ); // Filters to allow other code to extend the list of capabilities $additional_standard = apply_filters( 'add_et_support_standard_capabilities', array() ); $additional_elevated = apply_filters( 'add_et_support_elevated_capabilities', array() ); // Apply filter capabilities to our definitions $standard_capabilities = array_merge( $additional_standard, $standard_capabilities ); // Just like Elevated gets all of Standard's capabilities, it also inherits Standard's filter caps $elevated_capabilities = array_merge( $additional_standard, $additional_elevated, $elevated_capabilities ); // Create the standard ET Support role add_role( 'et_support', 'ET Support', $standard_capabilities ); $et_support_role = get_role( 'et_support' ); foreach ( $standard_capabilities as $cap ) { $et_support_role->add_cap( $cap ); } // Create the elevated ET Support role add_role( 'et_support_elevated', 'ET Support - Elevated', $elevated_capabilities ); $et_support_elevated_role = get_role( 'et_support_elevated' ); foreach ( $elevated_capabilities as $cap ) { $et_support_elevated_role->add_cap( $cap ); } } /** * Remove our Standard and Elevated Support roles * * @since 3.20 */ public function support_user_remove_roles() { // Divi Support :: Standard remove_role( 'et_support' ); // Divi Support :: Elevated remove_role( 'et_support_elevated' ); } /** * Set the ET Support User's role * * @since 3.20 * * @param string $role */ public function support_user_set_role( $role = '' ) { // Get the Divi Support User object $support_user = new WP_User( $this->support_user_account_name ); // Set the new Role switch ( $role ) { case 'et_support': $support_user->set_role( 'et_support' ); break; case 'et_support_elevated': $support_user->set_role( 'et_support_elevated' ); break; case '': default: $support_user->set_role( '' ); } } /** * Ensure the `unfiltered_html` capability is added to the ET Support roles in Multisite * * @since 3.22 * * @param array $caps An array of capabilities. * @param string $cap The capability being requested. * @param int $user_id The current user's ID. * * @return array Modified array of user capabilities. */ function support_user_map_meta_cap( $caps, $cap, $user_id ) { if ( ! $this->is_support_user( $user_id ) ) { return $caps; } // This user is in an ET Support user role, so add the capability if ( 'unfiltered_html' === $cap ) { $caps = array( 'unfiltered_html' ); } return $caps; } /** * Remove KSES filters on ET Support User's content * * @since 3.22 */ function support_user_kses_remove_filters() { if ( $this->is_support_user() ) { kses_remove_filters(); } } /** * Clear "Delete Account" cron hook * * @since 3.20 * * @return void */ public function support_user_clear_delete_cron() { wp_clear_scheduled_hook( $this->support_user_cron_name ); } /** * Delete the support account if it's expired or the expiration date is not set * * @since 3.20 * * @return void */ public function support_user_cron_maybe_delete_account() { if ( ! username_exists( $this->support_user_account_name ) ) { return; } if ( isset( $this->support_user_options['date_created'] ) ) { $this->support_user_maybe_delete_expired_account(); } else { // if the expiration date isn't set, delete the account anyway $this->support_user_delete_account(); } } /** * Schedule account removal check * * @since 3.20 * * @return void */ public function support_user_init_cron_delete_account() { $this->support_user_clear_delete_cron(); wp_schedule_event( time(), 'hourly', $this->support_user_cron_name ); } /** * Get plugin options * * @since 3.20 * * @return void */ public function support_user_get_options() { $this->support_user_options = get_option( $this->support_user_options_name ); } /** * Generate random token * * @since 3.20 * * @param integer $length Token Length * @param bool $include_symbols Whether to include special characters (or just stick to alphanumeric) * * @return string $token Generated token */ public function support_user_generate_token( $length = 17, $include_symbols = true ) { $alphanum = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $symbols = '!@$^*()-=+'; $token = substr( str_shuffle( $include_symbols ? $alphanum . $symbols : $alphanum ), 0, $length ); return $token; } /** * Generate password from token * * @since 3.20 * * @param string $token Token * * @return string|WP_Error Generated password if successful, WP Error object otherwise */ public function support_user_generate_password( $token ) { global $wp_version; $salt = ''; /** @see ET_Core_SupportCenter::maybe_set_site_id() */ $site_id = get_option( 'et_support_site_id' ); if ( empty( $site_id ) ) { return false; } // Site ID must be a string if ( ! is_string( $site_id ) ) { return false; } $et_license = $this->get_et_license(); if ( ! $et_license ) { return false; } $send_to_api = array( 'action' => 'get_salt', 'site_id' => esc_attr( $site_id ), 'username' => esc_attr( $et_license['username'] ), 'api_key' => esc_attr( $et_license['api_key'] ), 'site_url' => esc_url( home_url( '/' ) ), 'login_url' => 'https://www.elegantthemes.com/members-area/admin/token/' . '?url=' . urlencode( wp_login_url() ) . '&token=' . urlencode( $token . '|' . $site_id ), ); $support_user_options = array( 'timeout' => 30, 'body' => $send_to_api, 'user-agent' => 'WordPress/' . $wp_version . '; Support Center/' . ET_CORE_VERSION . '; ' . home_url( '/' ), ); $request = wp_remote_post( 'https://www.elegantthemes.com/api/token.php', $support_user_options ); // Early exit if we don't get a good HTTP response from the API server if ( 200 !== intval( wp_remote_retrieve_response_code( $request ) ) ) { return new WP_Error( 'et_remote_access', esc_html__( 'Elegant Themes API Error: HTTP error in API response', 'et-core' ) ); } // Early exit and pass along WP_Error report if the server response is an error if ( is_wp_error( $request ) ) { return new WP_Error( 'et_remote_access', esc_html__( 'Elegant Themes API Error: WordPress Error in API response', 'et-core' ) ); } // Otherwise the response is good - let's load it and continue $response = unserialize( wp_remote_retrieve_body( $request ) ); // If the API returns an error, we will return and log the accompanying message $response_is_error = array_key_exists( 'error', $response ); $response_has_error_message = array_key_exists( 'message', $response ); if ( $response_is_error && $response_has_error_message ) { return new WP_Error( 'et_remote_access', esc_html__( 'Elegant Themes API Error: ' . $response['message'], 'et-core' ) ); } // If we get an "Incorrect Token" response, delete the generated Site ID from database $response_is_token_error = array_key_exists( 'incorrect_token', $response ); if ( $response_is_token_error && ! empty( $response['incorrect_token'] ) ) { delete_option( 'et_support_site_id' ); return new WP_Error( 'et_remote_access', esc_html__( 'Elegant Themes API Error: Incorrect Token. Please, try again.', 'et-core' ) ); } // If we get a normal-looking response, but it doesn't contain the salt we need if ( empty( $response['salt'] ) ) { return new WP_Error( 'et_remote_access', esc_html__( 'Elegant Themes API Error: The API response was missing required data.', 'et-core' ) ); } // We have the salt; let's clean it and make sure we can use it $salt = sanitize_text_field( $response['salt'] ); if ( empty( $salt ) ) { return new WP_Error( 'et_remote_access', esc_html__( 'Elegant Themes API Error: The API responded, but the response was empty.', 'et-core' ) ); } // Generate the password using the token we were initially passed & the salt from the API $password = hash( 'sha256', $token . $salt ); return $password; } /** * Delete the account if it's expired * * @since 3.20 * * @return void */ public function support_user_maybe_delete_expired_account() { if ( empty( $this->support_user_options['date_created'] ) ) { return; } $expiration_date_unix = strtotime( $this->support_user_expiration_time, $this->support_user_options['date_created'] ); // Delete the user account if the expiration date is in the past if ( time() >= $expiration_date_unix ) { $this->support_user_delete_account(); } return; } /** * Delete support account and the plugin options ( token, expiration date ) * * @since 3.20 * * @return string | WP_Error Confirmation message on success, WP_Error on failure */ public function support_user_delete_account() { if ( defined( 'DOING_CRON' ) ) { require_once( ABSPATH . 'wp-admin/includes/user.php' ); } if ( ! username_exists( $this->support_user_account_name ) ) { return new WP_Error( 'get_user_data', esc_html__( 'Support account doesn\'t exist.', 'et-core' ) ); } $support_account_data = get_user_by( 'login', $this->support_user_account_name ); if ( $support_account_data ) { $support_account_id = $support_account_data->ID; if ( ( is_multisite() && ! wpmu_delete_user( $support_account_id ) ) || ( ! is_multisite() && ! wp_delete_user( $support_account_id ) ) ) { return new WP_Error( 'delete_user', esc_html__( 'Support account hasn\'t been removed. Try to regenerate token again.', 'et-core' ) ); } delete_option( $this->support_user_options_name ); } else { return new WP_Error( 'get_user_data', esc_html__( 'Cannot get the support account data. Try to regenerate token again.', 'et-core' ) ); } $this->support_user_remove_roles(); $this->support_user_remove_site_id(); $this->support_user_clear_delete_cron(); // update options variable $this->support_user_get_options(); new WP_Error( 'get_user_data', esc_html__( 'Token has been deleted successfully.', 'et-core' ) ); return esc_html__( 'Token has been deleted successfully. ', 'et-core' ); } /** * Maybe delete support account and the plugin options when switching themes * * If a theme change is one of: * - [Divi/Extra] > [Divi/Extra] child theme * - [Divi/Extra] child theme > [Divi/Extra] child theme * - [Divi/Extra] child theme > [Divi/Extra] * ...then we won't change the state of the Remote Access toggle. * * @since 3.23 * * @return string | WP_Error Confirmation message on success, WP_Error on failure */ public function maybe_deactivate_on_theme_switch() { // Don't do anything if the user isn't logged in if ( ! is_user_logged_in() ) { return; } // Don't do anything if the parent theme's name matches the parent of this Support Center instance if ( get_option( 'template' ) === $this->parent_nicename ) { return; } // Leaving Divi/Extra environment; deactivate Support Center $this->support_user_delete_account(); $this->unlist_support_center(); $this->support_center_capabilities_teardown(); } /** * Is this user the ET Support User? * * @since 3.22 * * @param int|null $user_id Pass a User ID to check. We'll get the current user's ID otherwise. * * @return bool Returns whether this user is the ET Support User. */ function is_support_user( $user_id = null ) { $user_id = $user_id ? (int) $user_id : get_current_user_id(); if ( ! $user_id ) { return false; } $user = get_userdata( $user_id ); if ( ! is_object( $user ) || ! property_exists( $user, 'roles' ) ) { return false; } // Gather this user's associated role(s). $user_roles = (array) $user->roles; $user_is_support = false; // First, check the username. if ( ! $this->support_user_account_name === $user->user_login ) { return $user_is_support; } // Determine whether this user has the ET Support User role. if ( in_array( 'et_support', $user_roles, true ) ) { $user_is_support = true; } if ( in_array( 'et_support_elevated', $user_roles, true ) ) { $user_is_support = true; } return $user_is_support; } /** * Delete support account and the plugin options ( token, expiration date ) * * @since 3.20 * * @return void */ public function unlist_support_center() { delete_option( 'et_support_center_installed' ); } /** * */ public function support_user_remove_site_id() { $site_id = get_option( 'et_support_site_id' ); if ( empty( $site_id ) ) { return; } // Site ID must be a string if ( ! is_string( $site_id ) ) { return; } $et_license = $this->get_et_license(); if ( ! $et_license ) { return; } $send_to_api = array( 'action' => 'remove_site_id', 'site_id' => esc_attr( $site_id ), 'username' => esc_attr( $et_license['username'] ), 'api_key' => esc_attr( $et_license['api_key'] ), 'site_url' => esc_url( home_url( '/' ) ), ); $settings = array( 'timeout' => 30, 'body' => $send_to_api, ); $request = wp_remote_post( 'https://www.elegantthemes.com/api/token.php', $settings ); } function support_user_update_via_ajax() { // Verify nonce et_core_security_check( 'manage_options', 'support_center', 'nonce' ); // Get POST data $support_update = sanitize_text_field( $_POST['support_update'] ); $response = array(); // Update option(s) if ( 'activate' === $support_update ) { $maybe_create_user = $this->support_user_maybe_create_user(); // Only activate if we have a User ID and Password if ( ! is_wp_error( $maybe_create_user ) ) { $this->support_user_set_role( 'et_support' ); $account_settings = get_option( $this->support_user_options_name ); $site_id = get_option( 'et_support_site_id' ); $response['expiry'] = strtotime( date( 'Y-m-d H:i:s ', $this->support_user_options['date_created'] ) . $this->support_user_expiration_time ); $response['token'] = ''; if ( ! empty( $site_id ) && is_string( $site_id ) ) { $account_setting_token = isset( $account_settings['token'] ) ? $account_settings['token'] : ''; $response['token'] = $account_setting_token . '|' . $site_id; } $response['message'] = esc_html__( 'ET Support User role has been activated.', 'et-core' ); } else { et_error( $maybe_create_user->get_error_message() ); $response['error'] = $maybe_create_user->get_error_message(); } } if ( 'elevate' === $support_update ) { $this->support_user_set_role( 'et_support_elevated' ); $response['message'] = esc_html__( 'ET Support User role has been elevated.', 'et-core' ); } if ( 'deactivate' === $support_update ) { $this->support_user_set_role( '' ); $this->support_user_delete_account(); $this->support_user_clear_delete_cron(); $response['message'] = esc_html__( 'ET Support User role has been deactivated.', 'et-core' ); } // `echo` data to return if ( isset( $response ) ) { echo json_encode( $response ); } // `die` when we're done wp_die(); } /** * SUPPORT CENTER :: SAFE MODE */ /** * ET Product Allowlist * * @since 3.28 * * @param string $product Potential ET product name that we want to confirm is on the list. * * @return string|false If the product is on our list, we return the "nice name" we have for it. Otherwise, we return FALSE. */ protected function is_allowlisted_product( $product = '' ) { switch ( $product ) { case 'divi_builder_plugin': case 'divi_theme': case 'extra_theme': case 'monarch_plugin': case 'bloom_plugin': case 'divi_dash_plugin': return $this->get_parent_nicename( $product ); break; default: return false; } } /** * Safe Mode: Set session cookie to temporarily disable Plugins * * @since 3.20 * * @return void */ function safe_mode_update_via_ajax() { et_core_security_check( 'manage_options', 'support_center', 'nonce' ); $response = array(); // Get POST data $support_update = sanitize_text_field( $_POST['support_update'] ); // Update option(s) if ( 'activate' === $support_update ) { // Check the ET product that is activating Safe Mode $safe_mode_activator = sanitize_key( $_POST['product'] ); // Confirm that this is a allowlisted product $allowlisted_product = $this->is_allowlisted_product( $safe_mode_activator ); if ( ! $allowlisted_product ) { // Send a failure code and exit the function header( "HTTP/1.0 403 Forbidden" ); print 'Bad or malformed ET product name.'; wp_die(); } $this->toggle_safe_mode( true, $safe_mode_activator ); $response['message'] = esc_html__( 'ET Safe Mode has been activated.', 'et-core' ); } if ( 'deactivate' === $support_update ) { $this->toggle_safe_mode( false ); $response['message'] = esc_html__( 'ET Safe Mode has been deactivated.', 'et-core' ); } $this->set_safe_mode_cookie(); // `echo` data to return if ( isset( $response ) ) { echo json_encode( $response ); } // `die` when we're done wp_die(); } /** * Toggle Safe Mode * * @since 3.20 * * @param bool $activate TRUE if enabling Safe Mode, FALSE if disabling Safe mode. * @param string $product Name of ET product that is activating Safe Mode (@see ET_Core_SupportCenter::get_parent_nicename()). */ public function toggle_safe_mode( $activate = true, $product = '' ) { $activate = (bool) $activate; $user_id = get_current_user_id(); $allowlisted_product = $this->is_allowlisted_product( $product ); // Only proceed with an activation request if it comes from a allowlisted product if ( $activate && ! $allowlisted_product ) { return; } update_user_meta( $user_id, '_et_support_center_safe_mode', $activate ? 'on' : 'off' ); update_user_meta( $user_id, '_et_support_center_safe_mode_product', $activate ? sanitize_text_field( $allowlisted_product ) : '' ); $activate ? $this->maybe_add_mu_autoloader() : $this->maybe_remove_mu_autoloader(); /** * Fires when safe mode is toggled on or off. * * @since 3.25.4 * * @param bool $state True if toggled on, false if toggled off. */ do_action( 'et_support_center_toggle_safe_mode', $activate ); } /** * Set Safe Mode Cookie * * @since 3.20 * * @return void */ function set_safe_mode_cookie() { if ( et_core_is_safe_mode_active() ) { // This random string ensures old cookies aren't used to view the site in Safe Mode $passport = md5( rand() ); update_option( 'et-support-center-safe-mode-verify', $passport ); setcookie( 'et-support-center-safe-mode', $passport, time() + DAY_IN_SECONDS, SITECOOKIEPATH, false, is_ssl() ); } else { // Force-expire the cookie setcookie( 'et-support-center-safe-mode', '', 1, SITECOOKIEPATH, false, is_ssl() ); } } /** * Render modal that intercepts plugin activation/deactivation * * @since 3.20 * * @return void */ public function render_safe_mode_block_restricted() { if ( ! et_core_is_safe_mode_active() ) { return; } // Get the name of the ET product that activated Safe Mode $safe_mode_activator = get_user_meta( get_current_user_id(), '_et_support_center_safe_mode_product', true ); $verified_activator = $this->is_allowlisted_product( $safe_mode_activator ); ?> is_allowlisted_product( $safe_mode_activator ); print sprintf( '%3$s', 'et-safe-mode-indicator', esc_url( get_admin_url( null, 'admin.php?page=et_support_center#et_card_safe_mode' ) ), esc_html__( sprintf( 'Turn Off %1$s Safe Mode', $verified_activator ), 'et-core' ) ); print sprintf( '
    %3$s
    ', 'et-ajax-saving', esc_url( $this->local_path . 'admin/images/ajax-loader.gif' ), 'loading' ); } } /** * Prints the admin page for Support Center * * @since 3.20 */ public function add_support_center() { $is_current_user_et_support = 0; if ( in_array( 'et_support', wp_get_current_user()->roles ) ) { $is_current_user_et_support = 1; } if ( in_array( 'et_support_elevated', wp_get_current_user()->roles ) ) { $is_current_user_et_support = 2; } // Conditionally Display Divi Hosting Card $this->maybe_display_divi_hosting_card(); ?>

    parent_nicename ), 'et-core' ); ?>

    current_user_can( 'et_support_center_system' ) ) { $card_title = esc_html__( 'System Status', 'et-core' ); $card_content = sprintf( '
    %1$s
    ' . '' . '
    %3$s %4$s %5$s
    ', et_core_intentionally_unescaped( $this->system_diagnostics_generate_report( true, 'div' ), 'html' ), et_core_intentionally_unescaped( $this->system_diagnostics_generate_report( true, 'plain' ), 'html' ), sprintf( '%1$s', esc_html__( 'Show Full Report', 'et-core' ) ), sprintf( '%1$s', esc_html__( 'Hide Full Report', 'et-core' ) ), sprintf( '%1$s', esc_html__( 'Copy Full Report', 'et-core' ) ) ); print $this->add_support_center_card( array( 'title' => $card_title, 'content' => $card_content, 'additional_classes' => array( 'et_system_status', 'summary', ), ) ); } /** * Run code after the 1st Support Center card has been output * * @since 3.20 */ do_action( 'et_support_center_below_position_1' ); // Build Card :: Remote Access if ( $this->current_user_can( 'et_support_center_remote_access' ) && ( 0 === $is_current_user_et_support ) ) { $card_title = esc_html__( 'Elegant Themes Support', 'et-core' ); $card_content = __( '

    Enabling Remote Access will give the Elegant Themes support team limited access to your WordPress Dashboard. If requested, you can also enable full admin privileges. Remote Access should only be turned on if requested by the Elegant Themes support team. Remote Access is automatically disabled after 4 days.

    ', 'et-core' ); $support_account = $this->get_et_support_user(); $is_et_support_user_active = 0; $has_et_license = $this->get_et_license(); if ( ! $has_et_license ) { $card_content .= sprintf( '

    %1$s

    %2$s

    ', esc_html__( 'Remote Access', 'et-core' ), __( 'Remote Access cannot be enabled because you do not have a valid API Key or your Elegant Themes subscription has expired. You can find your API Key by logging in to your Elegant Themes account. It should then be added to your Options Panel.', 'et-core' ) ); } else { if ( is_object( $support_account ) && property_exists( $support_account, 'roles' ) ) { if ( in_array( 'et_support', $support_account->roles ) ) { $is_et_support_user_active = 1; } if ( in_array( 'et_support_elevated', $support_account->roles ) ) { $is_et_support_user_active = 2; } } $support_user_active_state = ( intval( $is_et_support_user_active ) > 0 ) ? ' et_pb_on_state' : ' et_pb_off_state'; $expiry = ''; if ( ! empty( $this->support_user_options['date_created'] ) ) { // Calculate the 'Created Date' plus the 'Time To Expire' $date_created = date( 'Y-m-d H:i:s ', $this->support_user_options['date_created'] ); $expiry = strtotime( $date_created . $this->support_user_expiration_time ); } // Toggle Support User activation $card_content .= sprintf( '

    %1$s

    ' . '
    ' . '
    ' . '%3$s' . '' . '%4$s' . '
    ' . '%6$s' . '' . '' . '' . '
    ' . '
    ', esc_html__( 'Remote Access', 'et-core' ), esc_attr( $support_user_active_state ), esc_html__( 'Enabled', 'et-core' ), esc_html__( 'Disabled', 'et-core' ), esc_attr( $expiry ), esc_html__( 'Remote Access will be automatically disabled in: ', 'et-core' ), 'et_pb_yes_no_button', 'et_pb_value_text' ); // Toggle Support User role elevation (only visible if Support User is active) $extra_css = ( intval( $is_et_support_user_active ) > 0 ) ? 'style="display:block;"' : ''; $support_user_elevated_state = ( intval( $is_et_support_user_active ) > 1 ) ? ' et_pb_on_state' : ' et_pb_off_state'; $card_content .= sprintf( '

    %1$s

    ' . '
    ' . '
    ' . '%3$s' . '' . '%4$s' . '
    ' . '
    ' . '
    ', esc_html__( 'Activate Full Admin Privileges', 'et-core' ), esc_attr( $support_user_elevated_state ), esc_html__( 'Enabled', 'et-core' ), esc_html__( 'Disabled', 'et-core' ), et_core_intentionally_unescaped( $extra_css, 'html' ), 'et_pb_yes_no_button', 'et_pb_value_text' ); } // Add a "Copy Support Token" CTA if Remote Access is active $site_id = get_option( 'et_support_site_id' ); $support_token_cta = ''; if ( intval( $is_et_support_user_active ) > 0 && ! empty( $site_id ) && is_string( $site_id ) ) { $account_settings = get_option( $this->support_user_options_name ); $account_setting_token = isset( $account_settings['token'] ) ? $account_settings['token'] : ''; $support_token_cta = '' . esc_html__( 'Copy Support Token', 'et-core' ) . ''; } $vip_support_content = '
    ' . '
    ' . '' . 'Divi VIP Support' . '' . '
    ' . '
    ' . '

    ' . esc_html__( 'Get More With Divi VIP', 'et-core' ) . '

    ' . '

    ' . esc_html__( 'The Best Support, Even Faster.', 'et-core' ) . '

    ' . '

    ' . esc_html__( 'We want to provide exactly the level of support any of our customers need to be successful. With Divi VIP, you get faster support (Under 30 minutes response times around the clock). Keep your clients happy by letting us solve their problems faster.', 'et-core' ) . '

    ' . '' . esc_html__( 'Get Divi VIP Today!', 'et-core' ) . '' . '
    ' . '
    '; $card_content .= '
    ' . '' . esc_html__( 'Chat With Support', 'et-core' ) . '' . $support_token_cta . $vip_support_content . '
    '; print $this->add_support_center_card( array( 'title' => $card_title, 'content' => $card_content, 'additional_classes' => array( 'et_remote_access', 'et-epanel-box', ), ) ); } /** * Run code after the 2nd Support Center card has been output * * @since 3.20 */ do_action( 'et_support_center_below_position_2' ); // Build Card :: Divi Documentation & Help if ( $this->current_user_can( 'et_support_center_documentation' ) ) { switch ( $this->parent ) { case 'extra_theme': $documentation_url = 'https://www.elegantthemes.com/documentation/extra/'; break; case 'divi_theme': $documentation_url = 'https://www.elegantthemes.com/documentation/divi/'; break; case 'divi_builder_plugin': $documentation_url = 'https://www.elegantthemes.com/documentation/divi-builder/'; break; case 'monarch_plugin': $documentation_url = 'https://www.elegantthemes.com/documentation/monarch/'; break; case 'bloom_plugin': $documentation_url = 'https://www.elegantthemes.com/documentation/bloom/'; break; default: $documentation_url = 'https://www.elegantthemes.com/documentation/'; } $card_title = esc_html__( sprintf( '%1$s Documentation & Help', $this->parent_nicename ), 'et-core' ); $card_content = $this->get_documentation_video_player(); $card_content .= $this->get_documentation_articles_list(); $card_content .= ''; print $this->add_support_center_card( array( 'title' => $card_title, 'content' => $card_content, 'additional_classes' => array( 'et_documentation_help', 'et-epanel-box', ), ) ); } /** * Run code after the 3rd Support Center card has been output * * @since 3.20 */ do_action( 'et_support_center_below_position_3' ); // Build Card :: Safe Mode if ( $this->current_user_can( 'et_support_center_safe_mode' ) ) { $card_title = esc_html__( 'Safe Mode', 'et-core' ); $card_content = __( '

    Enabling Safe Mode will temporarily disable features and plugins that may be causing problems with your Elegant Themes product. This includes all Plugins, Child Themes, and Custom Code added to your integration areas. These items are only disabled for your current user session so your visitors will not be disrupted. Enabling Safe Mode makes it easy to figure out what is causing problems on your website by identifying or eliminating third party plugins and code as potential causes.

    ', 'et-core' ); $error_message = ''; $safe_mode_active = ( et_core_is_safe_mode_active() ) ? ' et_pb_on_state' : ' et_pb_off_state'; $plugins_list = array(); $plugins_output = ''; $has_mu_plugins_dir = wp_mkdir_p( WPMU_PLUGIN_DIR ) && wp_is_writable( WPMU_PLUGIN_DIR ); $can_create_mu_plugins_dir = wp_is_writable( WP_CONTENT_DIR ) && ! wp_mkdir_p( WPMU_PLUGIN_DIR ); if ( $has_mu_plugins_dir || $can_create_mu_plugins_dir ) { // Gather list of plugins that will be temporarily deactivated in Safe Mode $all_plugins = get_plugins(); $active_plugins = get_option( 'active_plugins' ); foreach ( $active_plugins as $plugin ) { // Verify this 'active' plugin actually exists in the plugins directory if ( ! in_array( $plugin, array_keys( $all_plugins ) ) ) { continue; } // If it's not in our allowlist, add it to the list of plugins we'll disable if ( ! in_array( $plugin, $this->safe_mode_plugins_allowlist ) ) { $plugins_list[] = '
  • ' . esc_html( $all_plugins[ $plugin ]['Name'] ) . '
  • '; } } } else { $error_message = et_get_safe_localization( sprintf( __( '

    Plugins cannot be disabled because your wp-content directory has inconsistent file permissions. Click here for more information.

    ', 'et-core' ), 'https://wordpress.org/support/article/changing-file-permissions/' ) ); } if ( count( $plugins_list ) > 0 ) { $plugins_output = sprintf( '

    %1$s

      %2$s
    ', esc_html__( 'The following plugins will be temporarily disabled for you only:', 'et-core' ), et_core_intentionally_unescaped( implode( ' ', $plugins_list ), 'html' ) ); } // Toggle Safe Mode activation $card_content .= sprintf( '
    ' . '
    ' . '
    ' . '%2$s' . '' . '%3$s' . '
    ' . '%4$s' . '%7$s' . '
    ' . '
    ', esc_attr( $safe_mode_active ), esc_html__( 'Enabled', 'et-core' ), esc_html__( 'Disabled', 'et-core' ), $plugins_output, 'et_pb_yes_no_button', 'et_pb_value_text', $error_message, esc_attr( $this->parent ) ); print $this->add_support_center_card( array( 'title' => $card_title, 'content' => $card_content, 'additional_classes' => array( 'et_safe_mode', 'et-epanel-box', ), ) ); } /** * Run code after the 4th Support Center card has been output * * @since 3.20 */ do_action( 'et_support_center_below_position_4' ); // Build Card :: Logs if ( $this->current_user_can( 'et_support_center_logs' ) ) { $debug_log_lines = apply_filters( 'et_debug_log_lines', 200 ); $wp_debug_log = $this->get_wp_debug_log( $debug_log_lines ); $card_title = esc_html__( 'Logs', 'et-core' ); $card_content = '

    If you have WP_DEBUG_LOG enabled, WordPress related errors will be archived in a log file. For your convenience, we have aggregated the contents of this log file so that you and the Elegant Themes support team can view it easily. The file cannot be edited here.

    '; if ( isset( $wp_debug_log['error'] ) ) { $card_content .= '
    ' . '' . '
    '; } else { $card_content .= '
    ' . '' . '' . '
    ' . ''; } print $this->add_support_center_card( array( 'title' => $card_title, 'content' => $card_content, 'additional_classes' => array( 'et_system_logs', 'et-epanel-box', ), ) ); } /** * Run code after all of the Support Center cards have been output * * @since 3.20 */ do_action( 'et_support_center_below_cards' ); ?>
    loading
    current_user_can( 'et_support_center_system' ) ) { return; } // Exit if Admin dismissed the Divi Hosting Card if ( get_option( 'et_hosting_card_dismissed', false ) ) { return; } // Show the Divi Hosting Card add_action( 'et_support_center_below_position_1', array( $this, 'print_divi_hosting_card' ) ); } /** * Prepare Settings for ET API request * Returns false when ET username/api_key is not found, and ET subscription is not active * * @since 4.4.7 * @param string $action * * @return bool|array */ protected function get_et_api_request_settings( $action ) { $et_account = et_core_get_et_account(); $et_username = et_()->array_get( $et_account, 'et_username', '' ); $et_api_key = et_()->array_get( $et_account, 'et_api_key', '' ); // Only when ET Username and ET API Key is found if ( '' !== $et_username && '' !== $et_api_key ) { global $wp_version; // Prepare settings for API request return array( 'timeout' => 30, 'body' => array( 'action' => $action, 'username' => $et_username, 'api_key' => $et_api_key, ), 'user-agent' => 'WordPress/' . $wp_version . '; Support Center/' . ET_CORE_VERSION . '; ' . home_url( '/' ), ); } return false; } /** * Check ET API whether ET User has disabled Divi Hosting Card * * @since 4.4.7 * * @return bool */ protected function maybe_api_has_hosting_card_disabled() { // Get API settings $api_settings = $this->get_et_api_request_settings( 'check_hosting_card_status' ); // Check API only when ET Username, ET API Key is found and Account is active if ( is_array( $api_settings ) ) { $request = wp_remote_post( 'https://www.elegantthemes.com/api/api.php', $api_settings ); $request_response_code = wp_remote_retrieve_response_code( $request ); // Do not show the Hosting Card when API Request, or, API Response has any error if ( is_wp_error( $request ) || 200 !== $request_response_code ) { return true; } $response_body = wp_remote_retrieve_body( $request ); $response = (array) json_decode( $response_body ); // Check whether the User has disabled the card if ( et_()->array_get( $response, 'success' ) && et_()->array_get( $response, 'status' ) === 'disabled' ) { // Mark it dismissed, so it won't be displayed anymore on this website update_option( 'et_hosting_card_dismissed', true ); // Do not show the Hosting Card return true; } } // Show the Hosting Card return false; } /** * Return Data for Divi Hosting Card * * @since 4.4.7 * * @return array */ protected function get_divi_hosting_features() { return array( 'title' => esc_html__( 'Get Recommended Divi Hosting', 'et-core' ), 'summary' => esc_html__( 'Upgrade your hosting to the most reliable, Divi-compatible hosting. Enjoy perfectly configured hosting environments pre-installed with the tools you need to be successful with Divi.', 'et-core' ), 'url' => 'https://www.elegantthemes.com/hosting/', 'learn_more' => esc_html__( 'Learn About Divi Hosting', 'et-core' ), 'dismiss_tooltip' => esc_html__( 'Remove This Recommendation On All Of Your Websites And Your Client\'s Websites Forever', 'et-core' ), 'features' => array( 'server' => array( 'title' => esc_html__( 'Divi-Optimized Servers', 'et-core' ), 'tooltip' => esc_html__( "We worked with our parters to make sure that their hosting solutions meet all of Divi's requirements out of the box. No hosting headaches on Divi Hosting.", 'et-core' ), ), 'speed' => array( 'title' => esc_html__( 'Blazing Fast Speed', 'et-core' ), 'tooltip' => esc_html__( 'Divi Hosting is powered by fast networks, modern hosting infrastructures and the latest server software. Plus you will enjoy automatic caching and a free CDN.', 'et-core' ), ), 'security' => array( 'title' => esc_html__( 'A Focus On Security', 'et-core' ), 'tooltip' => esc_html__( 'All of our hosting partners are dedicated to security. That means up-to-date server software and secure hosting practices.', 'et-core' ), ), 'backups' => array( 'title' => esc_html__( 'Automatic Backups', 'et-core' ), 'tooltip' => esc_html__( 'Every website needs backups! Each of our hosting partners provide automatic daily backups. If disaster strikes, these hosting companies have your back.', 'et-core' ), ), 'migrate' => array( 'title' => esc_html__( 'Easy Site Migration', 'et-core' ), 'tooltip' => esc_html__( "Already have a Divi website hosted somewhere else? All of our hosting partners provide migration tools or professional assisted migration. It's easy to switch to Divi Hosting!", 'et-core' ), ), 'staging' => array( 'title' => esc_html__( 'Easy Staging Sites', 'et-core' ), 'tooltip' => esc_html__( 'Automatic staging sites make it easy to develop new designs for your clients without disrupting visitors. Finish your work and push it live all at once.', 'et-core' ), ), ), ); } /** * Build and display Divi Hosting Card * * @since 4.4.7 */ public function print_divi_hosting_card() { // Gather System status data $report = $this->system_diagnostics_generate_report( false ); $result = array(); // Prepare the report data to check against when to show the Divi Hosting Card foreach ( $report as $status ) { $result[] = et_()->array_get( $status, 'pass_fail' ); } // Exit if any system status item is not in a warning state (red dot indicator) if ( ! in_array( 'fail', array_values( $result ), true ) ) { return; } // Exit if ET User has disabled the Divi Hosting card if ( $this->maybe_api_has_hosting_card_disabled() ) { return; } // JS dependency for Tooltips wp_enqueue_script( 'popper', $this->local_path . 'admin/js/popper.min.js', array( 'jquery' ), ET_CORE_VERSION ); wp_enqueue_script( 'tippy', $this->local_path . 'admin/js/tippy.min.js', array( 'jquery', 'popper' ), ET_CORE_VERSION ); $card = $this->get_divi_hosting_features(); $features = ''; // HTML Template for Features of the Divi Hosting Card foreach ( $card['features'] as $name => $feature ) { $features .= sprintf( '
    %2$s

    %3$s

    ', esc_html( $feature['tooltip'] ), sprintf( '', esc_url( "{$this->local_path}admin/images/svg/{$name}.svg" ) ), esc_html( $feature['title'] ) ); } // HTML Template for the Divi Hosting Card $card_content = sprintf( '

    %1$s

    %2$s
    %3$s
    ', esc_html( $card['summary'] ), et_core_esc_previously( $features ), sprintf( '%3$s', esc_url( $card['url'] ), esc_attr( $card['learn_more'] ), esc_html( $card['learn_more'] ) ) ); // Display the Divi Hosting Card print $this->add_support_center_card( array( 'title' => $card['title'], 'content' => $card_content, 'additional_classes' => array( 'et_hosting_card', ), 'dismiss_button' => array( 'card_key' => 'et_hosting_card', 'tooltip' => $card['dismiss_tooltip'], 'additional_classes' => array( 'et_hosting_card--dismiss', ), ), ) ); } } PKE\?x3k k components/cache/File.phpnu[WPFS()->is_readable( $file ) ) { self::$_cache[ $cache_name ] = unserialize( et_()->WPFS()->get_contents( $file ) ); } else { self::$_cache[ $cache_name ] = array(); } self::$_cache_loaded[ $cache_name ] = true; } return isset( self::$_cache[ $cache_name ] ) ? self::$_cache[ $cache_name ] : array(); } /** * Saves Cache. * * @since 3.27.3 * * @return void */ public static function save_cache() { if ( self::is_disabled() || ! self::$_dirty || ! self::$_cache ) { return; } foreach ( self::$_dirty as $cache_name ) { if ( ! isset( self::$_cache[ $cache_name ] ) ) { continue; } $data = self::$_cache[ $cache_name ]; $file = self::get_cache_file_name( $cache_name ); if ( ! wp_is_writable( dirname( $file ) ) ) { continue; } et_()->WPFS()->put_contents( $file, serialize( $data ) ); } } /** * Get full path of cache file name. * * The file name will be suffixed with .data * * @since 3.27.3 * * @param string $cache_name What is the file name that storing the cache data. * * @return string */ public static function get_cache_file_name( $cache_name ) { return sprintf( '%1$s/%2$s.data', ET_Core_PageResource::get_cache_directory(), $cache_name ); } /** * Check is file based caching is disabled. * * @since 4.0.8 * * @return bool */ public static function is_disabled() { return defined( 'ET_DISABLE_FILE_BASED_CACHE' ) && ET_DISABLE_FILE_BASED_CACHE; } } // Hook the shutdown action once. if ( ! has_action( 'shutdown', 'ET_Core_Cache_File::save_cache' ) ) { add_action( 'shutdown', 'ET_Core_Cache_File::save_cache' ); } PKE\K\components/cache/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\Fcomponents/cache/Directory.phpnu[_initialize(); } /** * Determines the cache directory path and url based on where we can write files * and whether or not the user has defined a custom path and url. * * @since 4.0.8 */ protected function _initialize() { $this->_initialize_wpfs(); if ( $this->_maybe_use_custom_path() ) { return; } $uploads_dir_info = (object) wp_get_upload_dir(); $path = et_()->path( WP_CONTENT_DIR, 'et-cache' ); $url = content_url( 'et-cache' ); $can_write = $this->wpfs->is_writable( $path ) && ! is_file( $path ); $can_create = ! $can_write && $this->wpfs->is_writable( WP_CONTENT_DIR ); if ( ! $can_write && ! $can_create && $this->wpfs->is_writable( $uploads_dir_info->basedir ) ) { // We can create our cache directory in the uploads directory $can_create = true; $path = et_()->path( $uploads_dir_info->basedir, 'et-cache' ); $url = et_()->path( $uploads_dir_info->baseurl, 'et-cache' ); } $this->can_write = $can_write || $can_create; $this->path = et_()->normalize_path( $path ); $this->url = $url; $this->_maybe_adjust_path_for_multisite( $uploads_dir_info ); /** * Absolute path to directory where we can store cache files. * * @since 4.0.8 * @var string */ define( 'ET_CORE_CACHE_DIR', $this->path ); /** * URL to {@see ET_CORE_CACHE_DIR}. * * @since 4.0.8 * @var string */ define( 'ET_CORE_CACHE_DIR_URL', $this->url ); $this->can_write && et_()->ensure_directory_exists( $this->path ); } /** * Ensures that the WP Filesystem API has been initialized. * * @since?? * * @return WP_Filesystem_Base */ protected function _initialize_wpfs() { require_once ABSPATH . 'wp-admin/includes/file.php'; /** * Filters the WP_Filesystem args. * * @since 4.18.1 * * @param $wpfs_args Arguments to use when initializing WP_Filesystem * * @return |array */ $wpfs_args = apply_filters( 'et_core_cache_wpfs_args', array() ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- may fail due to the permissions denied error if ( defined( 'ET_CORE_CACHE_DIR' ) && @WP_Filesystem( $wpfs_args, ET_CORE_CACHE_DIR, true ) ) { // We can write to a user-specified directory return $this->wpfs = $GLOBALS['wp_filesystem']; } // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- may fail due to the permissions denied error if ( @WP_Filesystem( $wpfs_args, false, true ) ) { // We can write to WP_CONTENT_DIR return $this->wpfs = $GLOBALS['wp_filesystem']; } $uploads_dir = (object) wp_get_upload_dir(); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- may fail due to the permissions denied error if ( @WP_Filesystem( $wpfs_args, $uploads_dir->basedir, true ) ) { // We can write to the uploads directory return $this->wpfs = $GLOBALS['wp_filesystem']; } // We aren't able to write to the filesystem so let's just make sure $this->wpfs // is an instance of the filesystem base class so that calling it won't cause errors. require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'; // Write notice to log when WP_DEBUG is enabled. $nl = PHP_EOL; $msg = 'Unable to write to filesystem. Please ensure that PHP has write access to one of '; $msg .= "the following directories:{$nl}{$nl}\t- WP_CONTENT_DIR{$nl}\t- wp_upload_dir(){$nl}\t- ET_CORE_CACHE_DIR."; et_debug( $msg ); return $this->wpfs = new WP_Filesystem_Base; } /** * Adjusts the path for multisite if necessary. * * @since 4.0.8 * * @param stdClass $uploads_dir_info (object) wp_get_upload_dir() */ protected function _maybe_adjust_path_for_multisite( $uploads_dir_info ) { if ( et_()->starts_with( $this->path, $uploads_dir_info->basedir ) || ! is_multisite() ) { return; } $site = get_site(); $network_id = $site->site_id; $site_id = $site->blog_id; $this->path = et_()->path( $this->path, $network_id, $site_id ); $this->url = et_()->path( $this->url, $network_id, $site_id ); } /** * Whether or not the user has defined a custom path for the cache directory. * * @since 4.0.8 * * @return bool */ protected function _maybe_use_custom_path() { if ( ! defined( 'ET_CORE_CACHE_DIR' ) ) { return false; } $this->path = ET_CORE_CACHE_DIR; if ( ! $this->can_write = $this->wpfs->is_writable( $this->path ) ) { et_wrong( 'ET_CORE_CACHE_DIR is defined but not writable.', true ); } if ( defined( 'ET_CORE_CACHE_DIR_URL' ) ) { $this->url = ET_CORE_CACHE_DIR_URL; } else { et_wrong( 'When ET_CORE_CACHE_DIR is defined, ET_CORE_CACHE_DIR_URL must also be defined.', true ); } return true; } /** * Returns the class instance. * * @since 4.0.8 * * @return ET_Core_Cache_Directory */ public static function instance() { if ( ! self::$_instance ) { self::$_instance = new self; } return self::$_instance; } } PKE\%3`components/cache/init.phpnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\<Ƌ"components/data/ScriptReplacer.phpnu[_map[ $id ] = $script; return $id; } public function map() { return $this->_map; } } PKE\n**components/data/init.phpnu[ $value ) { $parsed_value = is_array( $value ) ? implode( ' ', $value ) : $value; $output .= et_html_attr( $name, $parsed_value ); } return $output; } endif; if ( ! function_exists( 'et_sanitized_previously' ) ): /** * Semantical previously sanitized acknowledgement * * @deprecated {@see et_core_sanitized_previously()} * * @since 3.17.3 Deprecated * * @param mixed $value The value being passed-through * * @return mixed */ function et_sanitized_previously( $value ) { et_debug( "You're Doing It Wrong! Attempted to call " . __FUNCTION__ . "(), use et_core_sanitized_previously() instead." ); return $value; } endif; if ( ! function_exists( 'et_core_sanitized_previously' ) ): /** * Semantical previously sanitized acknowledgement * * @since 3.17.3 * * @param mixed $value The value being passed-through * * @return mixed */ function et_core_sanitized_previously( $value ) { return $value; } endif; if ( ! function_exists( 'et_core_esc_image_url' ) ) : /** * Escape image URL * * @since 4.27.1 * * @param string $url Image URL. * * @return string */ function et_core_esc_image_url( $url ) { return esc_url( $url, array( 'http', 'https', 'data' ) ); } endif; if ( ! function_exists( 'et_core_esc_attr' ) ): /** * Escape attribute value * * @since 3.27.1? * * @param string $attr_key Element attribute key. * @param (string|array) $attr_value Element attribute value. * * @return (string|array|WP_Error) */ function et_core_esc_attr( $attr_key, $attr_value ) { $attr_key = strtolower( $attr_key ); $allowed_attrs_default = array( // Filter style. // @see https://developer.wordpress.org/reference/functions/safecss_filter_attr/ 'style' => 'safecss_filter_attr', // We just pick some of the HTML attributes considered safe to use. 'data-*' => 'esc_attr', 'align' => 'esc_attr', 'alt' => 'esc_attr', 'autofocus' => 'esc_attr', 'autoplay' => 'esc_attr', 'class' => 'esc_attr', 'cols' => 'esc_attr', 'controls' => 'esc_attr', 'disabled' => 'esc_attr', 'height' => 'esc_attr', 'id' => 'esc_attr', 'max' => 'esc_attr', 'min' => 'esc_attr', 'multiple' => 'esc_attr', 'name' => 'esc_attr', 'placeholder' => 'esc_attr', 'required' => 'esc_attr', 'rows' => 'esc_attr', 'size' => 'esc_attr', 'sizes' => 'esc_attr', 'srcset' => 'esc_attr', 'step' => 'esc_attr', 'tabindex' => 'esc_attr', 'target' => 'esc_attr', 'title' => 'esc_attr', 'type' => 'esc_attr', 'value' => 'esc_attr', 'width' => 'esc_attr', // We just pick some of the HTML attributes containing a URL. // @see https://developer.wordpress.org/reference/functions/wp_kses_uri_attributes/ 'action' => 'esc_url', 'background' => 'et_core_esc_image_url', 'formaction' => 'esc_url', 'href' => 'esc_url', 'icon' => 'et_core_esc_image_url', 'poster' => 'et_core_esc_image_url', 'src' => 'et_core_esc_image_url', 'usemap' => 'esc_url', ); /** * Filters allowed attributes * * @since 3.27.1? * * @param array $allowed_attrs_default Key/value paired array, the key used as the attribute identifier, * the value used as the callback to escape the value. * @param string $attr_key Element attribute key. * @param (string|array) $attr_value Element attribute value. * * @return array */ $allowed_attrs = apply_filters( 'et_core_esc_attr', $allowed_attrs_default, $attr_key, $attr_value ); // Get attribute key callback. $callback = isset( $allowed_attrs[ $attr_key ] ) && 'data-*' !== $attr_key ? $allowed_attrs[ $attr_key ] : false; // Get data attribute key callback. if ( ! $callback && 'data-*' !== $attr_key && 0 === strpos( $attr_key, 'data-' ) && isset( $allowed_attrs['data-*'] ) ) { $callback = $allowed_attrs['data-*']; } if ( ! $callback || ! is_callable( $callback ) ) { return new WP_Error( 'invalid_attr_key', __( 'Invalid attribute key', 'et_builder' ) ); } if ( is_array( $attr_value ) ) { return array_map( $callback, $attr_value ); } // @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found return call_user_func( $callback, $attr_value ); } endif; if ( ! function_exists( 'et_core_sanitize_element_tag' ) ): /** * Sanitize element tag * * @since 3.27.1? * * @param string $tag Element tag. * * @return (string|WP_Error) */ function et_core_sanitize_element_tag( $tag ) { $tag = strtolower( $tag ); $headings = array( 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', ); // Bail early for heading tags. if ( in_array( $tag, $headings, true ) ) { return $tag; } $tag = preg_replace( '/[^a-z]/', '', $tag ); $disallowed_tags = array( 'applet', 'body', 'canvas', 'command', 'content', 'element', 'embed', 'frame', 'frameset', 'head', 'html', 'iframe', 'noembed', 'noframes', 'noscript', 'object', 'param', 'script', 'shadow', 'slot', 'style', 'template', 'title', 'xml', ); if ( empty( $tag ) || in_array( $tag, $disallowed_tags, true ) ) { return new WP_Error( 'invalid_element_tag', __( 'Invalid tag element', 'et_builder' ) ); } return $tag; } endif; /** * Pass thru semantical previously escaped acknowledgement * * @since 3.17.3 * * @param string value being passed through * @return string */ if ( ! function_exists( 'et_core_esc_previously' ) ) : function et_core_esc_previously( $passthru ) { return $passthru; } endif; /** * Pass thru function used to pacfify phpcs sniff. * Used when the nonce is checked elsewhere. * * @since 3.17.3 * * @return void */ if ( ! function_exists( 'et_core_nonce_verified_previously' ) ) : function et_core_nonce_verified_previously() { // :) } endif; /** * Pass thru semantical escaped by WordPress core acknowledgement * * @since 3.17.3 * * @param string value being passed through * @return string */ if ( ! function_exists( 'et_core_esc_wp' ) ) : function et_core_esc_wp( $passthru ) { return $passthru; } endif; /** * Pass thru semantical intentionally unescaped acknowledgement * * @since 3.17.3 * * @param string value being passed through * @param string excuse the value is allowed to be unescaped * @return string */ if ( ! function_exists( 'et_core_intentionally_unescaped' ) ) : function et_core_intentionally_unescaped( $passthru, $excuse ) { // Add valid excuses as they arise $valid_excuses = array( 'cap_based_sanitized', 'fixed_string', 'react_jsx', 'html', 'underscore_template', ); if ( ! in_array( $excuse, $valid_excuses ) ) { _doing_it_wrong( __FUNCTION__, esc_html__( 'This is not a valid excuse to not escape the passed value.', 'et_core' ), esc_html( et_get_theme_version() ) ); } return $passthru; } endif; /** * Sanitize value depending on user capability * * @since 3.17.3 * * @return string value being passed through */ if ( ! function_exists( 'et_core_sanitize_value_by_cap' ) ) : function et_core_sanitize_value_by_cap( $passthru, $sanitize_function = 'et_sanitize_html_input_text', $cap = 'unfiltered_html' ) { if ( ! current_user_can( $cap ) ) { $passthru = $sanitize_function( $passthru ); } return $passthru; } endif; /** * Pass thru semantical intentionally unsanitized acknowledgement * * @since 3.17.3 * * @param string value being passed through * @param string excuse the value is allowed to be unsanitized * @return string */ if ( ! function_exists( 'et_core_intentionally_unsanitized' ) ) : function et_core_intentionally_unsanitized( $passthru, $excuse ) { // Add valid excuses as they arise $valid_excuses = array(); if ( ! in_array( $excuse, $valid_excuses ) ) { _doing_it_wrong( __FUNCTION__, esc_html__( 'This is not a valid excuse to not sanitize the passed value.', 'et_core' ), esc_html( et_get_theme_version() ) ); } return $passthru; } endif; /** * Fixes unclosed HTML tags * * @since 3.18.4 * * @param string $content source HTML * * @return string */ if ( ! function_exists( 'et_core_fix_unclosed_html_tags' ) ): function et_core_fix_unclosed_html_tags( $content ) { // Exit if source has no HTML tags or we miss what we need to fix them anyway. if ( false === strpos( $content, '<' ) || ! class_exists( 'DOMDocument' ) ) { return $content; } $scripts = false; if ( false !== strpos( $content, '[\s\S]+?|', array( $scripts, 'replace' ), $content ); } $doc = new DOMDocument(); @$doc->loadHTML( sprintf( '%s%s', // Use WP charset sprintf( '', get_bloginfo( 'charset' ) ), $content ) ); if ( preg_match( '|([\s\S]+)|', $doc->saveHTML(), $matches ) ) { // Extract the fixed content. $content = $matches[1]; } if ( $scripts ) { // Replace placeholders with scripts. $content = strtr( $content, $scripts->map() ); } return $content; } endif; /** * Converts string to UTF-8 if mb_convert_encoding function exists * * @since 3.19.17 * * @param string $string source string * * @return string */ if ( ! function_exists( 'et_core_maybe_convert_to_utf_8' ) ): function et_core_maybe_convert_to_utf_8( $string ) { if ( function_exists( 'mb_convert_encoding' ) ) { return mb_convert_encoding( $string, 'UTF-8' ); } return $string; } endif; PKE\ttcomponents/data/Utils.phpnu[ array(), 'array_map' => array(), 'sort' => '__return_false', 'comparison' => '__return_false', ); /** * Generate an XML-RPC array. * * @param array $values * * @return string */ private function _create_xmlrpc_array( $values ) { $output = ''; foreach ( $values as $value ) { $output .= $this->_create_xmlrpc_value( $value ); } return "{$output}"; } /** * Generate an XML-RPC struct. * * @param array $members * * @return string */ private function _create_xmlrpc_struct( $members ) { $output = ''; foreach ( $members as $name => $value ) { $output .= sprintf( '%1$s%2$s', esc_html( $name ), $this->_create_xmlrpc_value( $value ) ); } return "{$output}"; } /** * Generate an XML-RPC value. * * @param mixed $value * * @return string */ private function _create_xmlrpc_value( $value ) { $output = ''; if ( is_string( $value ) ) { $value = esc_html( wp_strip_all_tags( $value ) ); $output = "{$value}"; } else if ( is_bool( $value ) ) { $value = (int) $value; $output = "{$value}"; } else if ( is_int( $value ) ) { $output = "{$value}"; } else if ( is_array( $value ) && $this->is_assoc_array( $value ) ) { $output = $this->_create_xmlrpc_struct( $value ); } else if ( is_array( $value ) ) { $output = $this->_create_xmlrpc_array( $value ); } return "{$output}"; } /** * Convert a SimpleXMLElement to a native PHP data type. * * @param SimpleXMLElement $value * * @return mixed */ private function _parse_value( $value ) { switch ( true ) { case is_string( $value ): $result = $value; break; case count( $value->struct ) > 0: $result = new stdClass(); foreach ( $value->struct->member as $member ) { $name = (string) $member->name; $member_value = $this->_parse_value( $member->value ); $result->$name = $member_value; } break; case count( $value->array ) > 0: $result = array(); foreach ( $value->array->data->value as $array_value ) { $result[] = $this->_parse_value( $array_value ); } break; case count( $value->i4 ) > 0: $result = (int) $value->i4; break; case count( $value->int ) > 0: $result = (int) $value->int; break; case count( $value->boolean ) > 0: $result = (boolean) $value->boolean; break; case count( $value->double ) > 0: $result = (double) $value->double; break; default: $result = (string) $value; } return $result; } private function _remove_empty_directories( $path ) { if ( ! is_dir( $path ) ) { return false; } $empty = true; $directory_contents = glob( untrailingslashit( $path ) . '/*' ); foreach ( (array) $directory_contents as $item ) { if ( ! $this->_remove_empty_directories( $item ) ) { $empty = false; } } return $empty ? @rmdir( $path ) : false; } public function _array_pick_callback( $item ) { $pick = $this->_pick; $value = $this->_pick_value; if ( is_array( $item ) && isset( $item[ $pick ] ) ) { return '_undefined_' !== $value ? $value === $item[ $pick ] : $item[ $pick ]; } else if ( is_object( $item ) && isset( $item->$pick ) ) { return '_undefined_' !== $value ? $value === $item->$pick : $item->$pick; } return false; } public function _array_sort_by_callback( $a, $b ) { $sort_by = $this->_sort_by; if ( is_array( $a ) ) { return strcmp( $a[ $sort_by ], $b[ $sort_by ] ); } else if ( is_object( $a ) ) { return strcmp( $a->$sort_by, $b->$sort_by ); } return 0; } /** * Returns `true` if all values in `$array` are not empty, `false` otherwise. * If `$condition` is provided then values are checked against it instead of `empty()`. * * @param array $array * @param bool $condition Compare values to this instead of `empty()`. Optional. * * @return bool */ public function all( array $array, $condition = null ) { if ( null === $condition ) { foreach( $array as $key => $value ) { if ( empty( $value ) ) { return false; } } } else { foreach( $array as $key => $value ) { if ( $value !== $condition ) { return false; } } } return true; } /** * Flattens a multi-dimensional array. * * @since 3.0.99 * * @param array $array An array to flatten. * * @return array */ function array_flatten( array $array ) { $iterator = new RecursiveIteratorIterator( new RecursiveArrayIterator( $array ) ); $use_keys = true; return iterator_to_array( $iterator, $use_keys ); } /** * Gets a value from a nested array using an address string. * * @param array $array An array which contains value located at `$address`. * @param string|array $address The location of the value within `$array` (dot notation). * @param mixed $default Value to return if not found. Default is an empty string. * * @return mixed The value, if found, otherwise $default. */ public function array_get( $array, $address, $default = '' ) { $keys = is_array( $address ) ? $address : explode( '.', $address ); $value = $array; foreach ( $keys as $key ) { if ( ! empty( $key ) && isset( $key[0] ) && '[' === $key[0] ) { $index = substr( $key, 1, -1 ); if ( is_numeric( $index ) ) { $key = (int) $index; } } if ( ! isset( $value[ $key ] ) ) { return $default; } $value = $value[ $key ]; } return $value; } /** * Wrapper for {@see self::array_get()} that sanitizes the value before returning it. * * @since 4.0.7 * * @param array $array An array which contains value located at `$address`. * @param string $address The location of the value within `$array` (dot notation). * @param mixed $default Value to return if not found. Default is an empty string. * @param string $sanitizer Sanitize function to use. Default is 'sanitize_text_field'. * * @return mixed The sanitized value if found, otherwise $default. */ public function array_get_sanitized( $array, $address, $default = '', $sanitizer = 'sanitize_text_field' ) { if ( $value = $this->array_get( $array, $address, $default ) ) { $value = $sanitizer( $value ); } return $value; } /** * Creates a new array containing only the items that have a key or property or only the items that * have a key or property that is equal to a certain value. * * @param array $array The array to pick from. * @param string|array $pick_by The key or property to look for or an array mapping the key or property * to a value to look for. * * @return array */ public function array_pick( $array, $pick_by ) { if ( is_string( $pick_by ) || is_int( $pick_by ) ) { $this->_pick = $pick_by; } else if ( is_array( $pick_by ) && 1 === count( $pick_by ) ) { $this->_pick = key( $pick_by ); $this->_pick_value = array_pop( $pick_by ); } else { return array(); } return array_filter( $array, array( $this, '_array_pick_callback' ) ); } /** * Sets a value in a nested array using an address string (dot notation) * * @see http://stackoverflow.com/a/9628276/419887 * * @param array $array The array to modify * @param string|array $path The path in the array * @param mixed $value The value to set */ public function array_set( &$array, $path, $value ) { $path_parts = is_array( $path ) ? $path : explode( '.', $path ); $current = &$array; foreach ( $path_parts as $key ) { if ( ! is_array( $current ) ) { $current = array(); } if ( '[' === $key[0] && is_numeric( substr( $key, 1, - 1 ) ) ) { $key = (int) $key; } $current = &$current[ $key ]; } $current = $value; } public function array_sort_by( $array, $key_or_prop ) { if ( ! is_string( $key_or_prop ) && ! is_int( $key_or_prop ) ) { return $array; } $this->_sort_by = $key_or_prop; if ( $this->is_assoc_array( $array ) ) { uasort( $array, array( $this, '_array_sort_by_callback' ) ); } else { usort( $array, array( $this, '_array_sort_by_callback' ) ); } return $array; } /** * Update a nested array value found at the provided path using {@see array_merge()}. * * @since 4.0.7 * * @param array $array * @param $path * @param $value */ public function array_update( &$array, $path, $value ) { $current_value = $this->array_get( $array, $path, array() ); $this->array_set( $array, $path, array_merge( $current_value, $value ) ); } /** * Whether or not a string ends with a substring. * * @since 4.5.3 * * @param string $haystack The string to look in. * @param string $needle The string to look for. * * @return bool */ public function ends_with( $haystack, $needle ) { $length = strlen( $needle ); if ( 0 === $length ) { return true; } return ( substr( $haystack, -$length ) === $needle ); } public function ensure_directory_exists( $path ) { if ( file_exists( $path ) ) { return is_dir( $path ); } // Try to create the directory $path = $this->normalize_path( $path ); if ( ! $this->WPFS()->mkdir( $path ) ) { // Walk up the tree and create any missing parent directories $this->ensure_directory_exists( dirname( $path ) ); $this->WPFS()->mkdir( $path ); } return is_dir( $path ); } public static function instance() { if ( ! self::$_instance ) { self::$_instance = new ET_Core_Data_Utils(); } return self::$_instance; } /** * Determine if an array has any `string` keys (thus would be considered an object in JSON) * * @param $array * * @return bool */ public function is_assoc_array( $array ) { return is_array( $array ) && count( array_filter( array_keys( $array ), 'is_string' ) ) > 0; } /** * Determine if value is an XML-RPC error. * * @param SimpleXMLElement $value * * @return bool */ public function is_xmlrpc_error( $value ) { return is_object( $value ) && isset( $value->faultCode ); } /** * Replaces any Windows style directory separators in $path with Linux style separators. * Windows actually supports both styles, even mixed together. However, its better not * to mix them (especially when doing string comparisons on paths). * * @since 4.0.8 Use {@see wp_normalize_path()} if it exists. Remove all occurrences of '..' from paths. * @since 3.0.52 * * @param string $path * * @return string */ public function normalize_path( $path = '' ) { $path = (string) $path; $path = str_replace( '..', '', $path ); if ( function_exists( 'wp_normalize_path' ) ) { return wp_normalize_path( $path ); } return str_replace( '\\', '/', $path ); } /** * Generate post data for a XML-RPC method call * * @param string $method_name * @param array $params * * @return string */ public function prepare_xmlrpc_method_call( $method_name, $params = array() ) { $output = ''; foreach ( $params as $param ) { $value = $this->_create_xmlrpc_value( $param ); $output .= "{$value}"; } $method_name = esc_html( $method_name ); return " {$method_name} {$output} "; } /** * Disable XML entity loader. * * @since 4.7.5 Don't execute deprecated `libxml_disable_entity_loader()` on PHP 8.0. * * @param bool $disable * * @return void */ public function libxml_disable_entity_loader( $disable ) { // The `libxml_disable_entity_loader()` method is deprecated since PHP 8.0 because // PHP 8.0 and later uses libxml versions from 2.9.0, which disabled XXE by default. if ( PHP_VERSION_ID < 80000 && function_exists( 'libxml_disable_entity_loader' ) ) { libxml_disable_entity_loader( $disable ); } } /** * Securely use simplexml_load_string. * * @param string $data XML data string. * * @return SimpleXMLElement */ public function simplexml_load_string( $data ) { $this->libxml_disable_entity_loader( true ); return simplexml_load_string( $data ); } /** * Creates a path string using the provided arguments. * * Examples: * - ``` * et_()->path( '/this/is', 'a', 'path' ); * // Returns '/this/is/a/path' * ``` * - ``` * et_()->path( ['/this/is', 'a', 'path', 'to', 'file.php'] ); * // Returns '/this/is/a/path/to/file.php' * ``` * * @since 4.0.6 * * @param string|string[] ...$parts * * @return string */ public function path() { $parts = func_get_args(); $path = ''; if ( 1 === count( $parts ) && is_array( reset( $parts ) ) ) { $parts = array_pop( $parts ); } foreach ( $parts as $part ) { $path .= "{$part}/"; } return substr( $path, 0, -1 ); } /** * Process an XML-RPC response string. * * @param $response * * @return mixed */ public function process_xmlrpc_response( $response, $skip_processing = false ) { $response = $this->simplexml_load_string( $response ); $result = array(); if ( $skip_processing ) { return $response; } if ( count( $response->fault ) > 0 ) { // An error was returned return $this->_parse_value( $response->fault->value ); } $single = count( $response->params->param ) === 1; foreach ( $response->params->param as $param ) { $value = $this->_parse_value( $param->value ); if ( $single ) { return $value; } else { $result[] = $value; } } return $result; } /** * Removes empty directories recursively starting at and (possibly) including `$path`. `$path` must be * an absolute path located under {@see WP_CONTENT_DIR}. Current user must have 'manage_options' * capability. If the path or permissions check fails, no directories will be removed. * * @param string $path Absolute path to parent directory. */ public function remove_empty_directories( $path ) { $path = realpath( $path ); if ( empty( $path ) ) { // $path doesn't exist return; } $path = $this->normalize_path( $path ); $content_dir = $this->normalize_path( WP_CONTENT_DIR ); if ( 0 !== strpos( $path, $content_dir ) || $content_dir === $path ) { return; } $capability = 0 === strpos( $path, "{$content_dir}/cache/et" ) ? 'edit_posts' : 'manage_options'; if ( ! wp_doing_cron() && ! et_core_security_check_passed( $capability ) ) { return; } $this->_remove_empty_directories( $path ); } /** * Whether or not a value includes another value. * * @param mixed $haystack The value to look in. * @param string $needle The value to look for. * * @return bool */ public function includes( $haystack, $needle ) { if ( is_string( $haystack ) ) { return false !== strpos( $haystack, $needle ); } if ( is_object( $haystack ) ) { return property_exists( $haystack, $needle ); } if ( is_array( $haystack ) ) { return in_array( $needle, $haystack ); } return false; } public function sanitize_text_fields( $fields ) { if ( ! is_array( $fields ) ) { return sanitize_text_field( $fields ); } $result = array(); foreach ( $fields as $field_id => $field_value ) { $field_id = sanitize_text_field( $field_id ); if ( is_array( $field_value ) ) { $field_value = $this->sanitize_text_fields( $field_value ); } else { $field_value = sanitize_text_field( $field_value ); } $result[ $field_id ] = $field_value; } return $result; } /** * Recursively traverses an array and escapes the keys and values according to passed escaping function. * * @since 3.17.3 * * @param array $values The array to be recursively escaped. * @param string $escaping_function The escaping function to be used on keys and values. Default 'esc_html'. Optional. * * @return array */ public function esc_array( $values, $escaping_function = 'esc_html' ) { if ( ! is_array( $values ) ) { return $escaping_function( $values ); } $result = array(); foreach ( $values as $key => $value ) { $key = $escaping_function( $key ); if ( is_array( $value ) ) { $value = $this->esc_array( $value, $escaping_function ); } else { $value = $escaping_function( $value ); } $result[ $key ] = $value; } return $result; } /** * Transforms an array of data into a new array based on the provided transformation definition. * * @since 3.10 Renamed from `transform_data_to` to `array_transform`. * @since 3.0.68 * * @param array $data The data to transform. * @param array $data_map Transformation definition. See examples below. * @param string $direction The direction in which to transform. Accepts '->', '<-'. Default '->' * @param array $exclude_keys Keys that should be excluded from the result. Optional. * * @return array */ public function array_transform( $data, $data_map, $direction = '->', $exclude_keys = array() ) { $result = array(); if ( ! in_array( $direction, array( '->', '<-' ) ) ) { return $result; } foreach ( $data_map as $address_1 => $address_2 ) { $from_address = '->' === $direction ? $address_1 : $address_2; $to_address = '->' === $direction ? $address_2 : $address_1; $array_value_required = $negate_bool_value = false; if ( 0 === strpos( $to_address, '@' ) || 0 === strpos( $from_address, '@' ) ) { $array_value_required = true; $to_address = ltrim( $to_address, '@' ); $from_address = ltrim( $from_address, '@' ); } else if ( 0 === strpos( $to_address, '!' ) || 0 === strpos( $from_address, '!' ) ) { $negate_bool_value = true; $to_address = ltrim( $to_address, '!' ); $from_address = ltrim( $from_address, '!' ); } if ( ! empty( $exclude_keys ) && array_key_exists( $to_address, $exclude_keys ) ) { continue; } $value = $this->array_get( $data, $from_address, null ); if ( null === $value ) { // Unknown key, skip it. continue; } if ( $array_value_required && ! is_array( $value ) ) { $value = array( $value ); } else if ( $negate_bool_value ) { $value = (bool) $value; $value = ! $value; } $this->array_set( $result, $to_address, $value ); } return $result; } /** * Converts xml data to array. Useful in cases where the xml doesn't adhere to XML-RPC spec. * * @param string|\SimpleXMLElement $xml_data * * @return array */ public function xml_to_array( $xml_data ) { if ( is_string( $xml_data ) ) { $xml_data = $this->simplexml_load_string( $xml_data ); } $json = wp_json_encode( $xml_data ); return json_decode( $json, true ); } /** * Make sure that in provided selector do not exist sub-selectors that targets inputs placeholders * * If they exist they should be split in an apart selector. * * @param string $selector * * @return array Return a list of selectors */ public function sanitize_css_placeholders( $selector ) { $selectors = explode( ',', $selector ); $selectors = array_map( 'trim', $selectors ); $selectors = array_filter( $selectors ); $main_selector = array(); $exceptions = array(); $placeholders = array( '::-webkit-input-placeholder', '::-moz-placeholder', ':-ms-input-placeholder', ); // No need to sanitize if is a single selector or even no selectors at all // Also if selectors do not contain placeholder meta-selector if ( count( $selectors ) < 2 || ! preg_match( '/' . implode( '|', $placeholders ) . '/', $selector ) ) { return array( $selector ); } foreach ( $selectors as $_selector ) { foreach ( $placeholders as $placeholder ) { if ( strpos( $_selector, $placeholder ) !== false ) { $exceptions[] = $_selector; continue 2; } } $main_selector[] = $_selector; } return array_filter( array_merge( array( implode( ', ', $main_selector ) ), $exceptions ) ); } /** * Whether or not a string starts with a substring. * * @since 4.0 * * @param string $string * @param string $substring * * @return bool */ public function starts_with( $string, $substring ) { return 0 === strpos( $string, $substring ); } /** * Convert string to camel case format. * * @since 4.0 * * @param string $string Original string data. * @param array $no_strip Additional regex pattern exclusion. * * @return string */ public function camel_case( $string, $no_strip = array() ) { $words = preg_split( '/[^a-zA-Z0-9' . implode( '', $no_strip ) . ']+/i', strtolower( $string ) ); if ( count( $words ) === 1 ) { return $words[0]; } $camel_cased = implode( '', array_map( 'ucwords', $words ) ); $camel_cased[0] = strtolower( $camel_cased[0] ); return $camel_cased; } /** * Returns the WP Filesystem instance. * * @since 4.0.6 * * @return WP_Filesystem_Base {@see ET_Core_PageResource::wpfs()} */ public function WPFS() { return et_core_cache_dir()->wpfs; } /** * Equivalent of usort but preserves relative order of equally weighted values. * * @since 4.0.9 * * @param array &$array * @param callable $comparison_function * * @return array */ public function usort( &$array, $comparison_function ) { return $this->_user_sort( $array, 'usort', $comparison_function ); } /** * Equivalent of uasort but preserves relative order of equally weighted values. * * @since 4.0.9 * * @param array &$array * @param callable $comparison_function * * @return array */ public function uasort( &$array, $comparison_function ) { return $this->_user_sort( $array, 'uasort', $comparison_function ); } /** * Equivalent of uksort but preserves relative order of equally weighted values. * * @since 4.0.9 * * @param array &$array * @param callable $comparison_function * * @return array */ public function uksort( &$array, $comparison_function ) { return $this->_user_sort( $array, 'uksort', $comparison_function ); } /** * Returns a string with a valid CSS property value. * * With some locales (ex: ro_RO) the decimal point can be ',' (comma) and * we need to convert that to a '.' (period) decimal point to ensure that * the value is a valid CSS property value. * * @since 4.4.8 * * @param float $float Original float value. * * @return string */ public function to_css_decimal( $float ) { return strtr( $float, ',', '.' ); } /** * Sort using a custom function accounting for the common undefined order * pitfall due to a return value of 0. * * @since 4.0.9 * * @param array &$array Array to sort * @param callable $sort_function "usort", "uasort" or "uksort" * @param callable $comparison_function Custom comparison function * * @return array */ protected function _user_sort( &$array, $sort_function, $comparison_function ) { $allowed_sort_functions = array( 'usort', 'uasort', 'uksort' ); if ( ! $this->includes( $allowed_sort_functions, $sort_function ) ) { _doing_it_wrong( __FUNCTION__, esc_html__( 'Only custom sorting functions can be used.', 'et_core' ), esc_html( et_get_theme_version() ) ); } // Use properties temporarily to pass values in order to preserve PHP 5.2 support. $this->sort_arguments['array'] = $array; $this->sort_arguments['sort'] = $sort_function; $this->sort_arguments['comparison'] = $comparison_function; $this->sort_arguments['array_map'] = 'uksort' === $sort_function ? array_flip( array_keys( $array ) ) : array_values( $array ); $sort_function( $array, array( $this, '_user_sort_callback' ) ); $this->sort_arguments['array'] = array(); $this->sort_arguments['array_map'] = array(); $this->sort_arguments['sort'] = '__return_false'; $this->sort_arguments['comparison'] = '__return_false'; return $array; } /** * Sort callback only meant to acompany self::sort(). * Do not use outside of self::_user_sort(). * * @since 4.0.9 * * @param mixed $a * @param mixed $b * * @return integer */ protected function _user_sort_callback( $a, $b ) { // @phpcs:ignore Generic.PHP.ForbiddenFunctions.Found $result = (int) call_user_func( $this->sort_arguments['comparison'], $a, $b ); if ( 0 !== $result ) { return $result; } if ( 'uksort' === $this->sort_arguments['sort'] ) { // Intentional isset() use for performance reasons. $a_order = isset( $this->sort_arguments['array_map'][ $a ] ) ? $this->sort_arguments['array_map'][ $a ] : false; $b_order = isset( $this->sort_arguments['array_map'][ $b ] ) ? $this->sort_arguments['array_map'][ $b ] : false; } else { $a_order = array_search( $a, $this->sort_arguments['array_map'] ); $b_order = array_search( $b, $this->sort_arguments['array_map'] ); } if ( false === $a_order || false === $b_order ) { // This should not be possible so we fallback to the undefined // sorting behavior by returning 0. return 0; } return $a_order - $b_order; } /** * Returns RFC 4211 compliant Universally Unique Identifier (UUID) version 4 * https://tools.ietf.org/html/rfc4122 * * @since 4.5.0 * * @param array $random_sequence The initial random sequence. Mostly used for test purposes. * * @return string */ public static function uuid_v4( $random_sequence = null ) { $buffer = array(); for ( $i = 0; $i < 16; $i++) { $buffer[] = isset( $random_sequence[ $i ] ) ? $random_sequence[ $i ] : mt_rand(0, 0xff); } // The high field of the timestamp multiplexed with the version number $buffer[6] = ( $buffer[6] & 0x0f ) | 0x40; // The high field of the clock sequence multiplexed with the variant $buffer[8] = ( $buffer[8] & 0x3f ) | 0x80; return sprintf( '%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x', // Time low $buffer[0], $buffer[1], $buffer[2], $buffer[3], // Time mid $buffer[4], $buffer[5], // Time hi and version $buffer[6], $buffer[7], // Clock seq hi and reserved $buffer[8], // Clock seq low $buffer[9], // Node $buffer[10], $buffer[11], $buffer[12], $buffer[13], $buffer[14], $buffer[15] ); } /** * Append/Prepend to comma separated selectors. * * Example: * * @see UtilsTest::testAppendPrependCommaSeparatedSelectors() * * @param string $css_selector Comma separated CSS selectors. * @param string $value Value to append/prepend. * @param string $prefix_suffix Values can be `prefix` or `suffix`. * @param bool $is_space_required Is space required? // phpcs:ignore Squiz.Commenting.FunctionComment.ParamCommentFullStop -- Respecting punctuation. * * @return string */ public function append_prepend_comma_separated_selectors( $css_selector, $value, $prefix_suffix, $is_space_required = true ) { $css_selectors = explode( ',', $css_selector ); $css_selectors_processed = array(); $is_prefix = 'prefix' === $prefix_suffix; foreach ( $css_selectors as $selector ) { $selector = rtrim( ltrim( $selector ) ); if ( $is_prefix && $is_space_required ) { $css_selectors_processed[] = sprintf( '%2$s %1$s', $selector, $value ); } elseif ( $is_prefix && ! $is_space_required ) { $css_selectors_processed[] = sprintf( '%2$s%1$s', $selector, $value ); } elseif ( ! $is_prefix && $is_space_required ) { $css_selectors_processed[] = sprintf( '%1$s %2$s', $selector, $value ); } elseif ( ! $is_prefix && ! $is_space_required ) { $css_selectors_processed[] = sprintf( '%1$s%2$s', $selector, $value ); } } return implode( ',', $css_selectors_processed ); } /** * Helper function to prepare attributes for SVG. * * @param array $props Props. * * @return string */ public function get_svg_attrs( $props ) { $result = ''; $attrs = array_merge( $props, array( 'xmlns' => 'http://www.w3.org/2000/svg', ) ); foreach ( $attrs as $key => $value ) { $result .= " {$key}=\"{$value}\""; } return $result; } } function et_core_data_utils_minify_css( $string = '' ) { $comments = <<< EOS (?sx) # don't change anything inside of quotes ( "(?:[^"\\\]++|\\\.)*+" | '(?:[^'\\\]++|\\\.)*+' ) | # comments /\* (?> .*? \*/ ) EOS; $everything_else = <<< EOS (?six) # don't change anything inside of quotes ( "(?:[^"\\\]++|\\\.)*+" | '(?:[^'\\\]++|\\\.)*+' ) | # spaces before and after ; and } \s*+ ; \s*+ ( } ) \s*+ | # all spaces around meta chars/operators (excluding + and -) \s*+ ( [*$~^|]?+= | [{};,>~] | !important\b ) \s*+ | # all spaces around + and - (in selectors only!) \s*([+-])\s*(?=[^}]*{) | # spaces right of ( [ : ( [[(:] ) \s++ | # spaces left of ) ] \s++ ( [])] ) | # spaces left (and right) of : (but not in selectors)! \s+(:)(?![^\}]*\{) | # spaces at beginning/end of string ^ \s++ | \s++ \z | # double spaces to single (\s)\s+ EOS; $search_patterns = array( "%{$comments}%", "%{$everything_else}%" ); $replace_patterns = array( '$1', '$1$2$3$4$5$6$7$8' ); return preg_replace( $search_patterns, $replace_patterns, $string ); } PKE\2O3:3:components/api/Service.phpnu[request} * * @since 1.1.0 * @var \ET_Core_HTTPRequest? */ public $request; /** * Convenience accessor for {@link self::http->response} * * @since 1.1.0 * @var \ET_Core_HTTPResponse? */ public $response; /** * For services that return JSON responses, this is the top-level/root key for the returned data. * * @since 1.1.0 * @var string */ public $response_data_key; /** * The service type (email, social, etc). * * @since 1.1.0 * @var string */ public $service_type; /** * The slug for this service (not shown in the UI). * * @since 1.1.0 * @var string */ public $slug; /** * Whether or not the service uses OAuth. * * @since 1.1.0 * @var bool */ public $uses_oauth; /** * Data Utility class. * * @var ET_Core_Data_Utils */ public $data_utils; // phpcs:disable ET.Sniffs.ValidVariableName.PropertyNotSnakeCase -- Existing codebase. /** * Error message for when API Key is required. * * @var string */ public $API_KEY_REQUIRED; // phpcs:enable ET.Sniffs.ValidVariableName.PropertyNotSnakeCase -- Existing codebase. /** * ET_Core_API_Service constructor. * * @since 1.1.0 * * @param string $owner {@see self::owner} * @param string $account_name The name of the service account that the instance will provide access to. * @param string $api_key The api key for the account. Optional (can be set after instantiation). */ public function __construct( $owner = 'ET_Core', $account_name = '', $api_key = '' ) { $this->account_name = str_replace( '.', '', sanitize_text_field( $account_name ) ); $this->owner = sanitize_text_field( $owner ); $this->account_fields = $this->get_account_fields(); $this->data = $this->_get_data(); $this->data_keys = $this->get_data_keymap(); $this->oauth_verifier = ''; $this->http = new ET_Core_HTTPInterface( $this->owner ); self::$_ = $this->data_utils = new ET_Core_Data_Utils(); $this->FAILURE_MESSAGE = esc_html__( 'API request failed, please try again.', 'et_core' ); $this->API_KEY_REQUIRED = esc_html__( 'API request failed. API Key is required.', 'et_core' ); if ( '' !== $api_key ) { $this->data['api_key'] = sanitize_text_field( $api_key ); $this->save_data(); } if ( $this->uses_oauth && $this->is_authenticated() ) { $this->_initialize_oauth_helper(); } } /** * Generates a HTTP Basic Auth header and adds it to the current request object. Uses the value * of {@link self::http_auth} to determine the correct values to use for the username and password. */ protected function _add_http_auth_header_to_request() { $username_key = $this->http_auth['username']; $password_key = $this->http_auth['password']; $username = isset( $this->data[ $username_key ] ) ? $this->data[ $username_key ] : $username_key; $password = isset( $this->data[ $password_key ] ) ? $this->data[ $password_key ] : $password_key; $this->request->HEADERS['Authorization'] = 'Basic ' . base64_encode( "{$username}:{$password}" ); } /** * Exchange a request/verifier token for an access token. This is the last step in the OAuth authorization process. * If successful, the access token will be saved and used for future calls to the API. * * @return bool Whether or not authentication was successful. */ private function _do_oauth_access_token_request() { if ( ! $this->_initialize_oauth_helper() ) { return false; } $args = array(); if ( '' !== $this->oauth_verifier ) { $args['oauth_verifier'] = $this->oauth_verifier; } $this->request = $this->http->request = $this->OAuth_Helper->prepare_access_token_request( $args ); $this->request->HEADERS['Content-Type'] = 'application/x-www-form-urlencoded'; $this->http->make_remote_request(); $this->response = $this->http->response; if ( $this->response->ERROR ) { return false; } $this->OAuth_Helper->process_authentication_response( $this->response, $this->http->expects_json ); if ( null === $this->OAuth_Helper->token ) { return false; } $this->data['access_key'] = $this->OAuth_Helper->token->key; $this->data['access_secret'] = $this->OAuth_Helper->token->secret; $this->data['is_authorized'] = true; if ( ! empty( $this->OAuth_Helper->token->refresh_token ) ) { $this->data['refresh_token'] = $this->OAuth_Helper->token->refresh_token; } // If there an `instance_url` returned from the auth response, save it. // Salesforce API should use this URL instead of the `login_url` provided by user. if ( ! empty( $this->OAuth_Helper->INSTANCE_URL ) ) { // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change the prop name. $this->data['instance_url'] = $this->OAuth_Helper->INSTANCE_URL; // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change the prop name. } return true; } /** * The service's private data. * * @see self::$_data * @internal * @since 1.1.0 * * @return array */ protected function _get_data() { return (array) get_option( "et_core_api_{$this->service_type}_options" ); } /** * Initializes {@link self::OAuth_Helper} * * @return bool `true` if successful, `false` otherwise. */ protected function _initialize_oauth_helper() { if ( null !== $this->OAuth_Helper ) { return true; } $urls = array( 'access_token_url' => $this->ACCESS_TOKEN_URL, 'request_token_url' => $this->REQUEST_TOKEN_URL, 'authorization_url' => $this->AUTHORIZATION_URL, 'redirect_url' => $this->REDIRECT_URL, ); $this->OAuth_Helper = new ET_Core_API_OAuthHelper( $this->data, $urls, $this->owner ); return null !== $this->OAuth_Helper; } /** * Returns the currently known custom fields for this service. * * @return array */ protected function _get_custom_fields() { return empty( $this->data['custom_fields'] ) ? array() : $this->data['custom_fields']; } /** * Initiate OAuth Authorization Flow * * @return array|bool */ public function authenticate() { et_core_nonce_verified_previously(); if ( '1.0a' === $this->oauth_version || ( '2.0' === $this->oauth_version && ! empty( $_GET['code'] ) ) ) { $authenticated = $this->_do_oauth_access_token_request(); if ( $authenticated ) { $this->save_data(); return true; } } elseif ( '2.0' === $this->oauth_version ) { $nonce = wp_create_nonce( 'et_core_api_service_oauth2' ); $args = array( 'client_id' => $this->data['api_key'], 'response_type' => 'code', 'state' => rawurlencode( "ET_Core|{$this->slug}|{$this->account_name}|{$nonce}" ), 'redirect_uri' => $this->REDIRECT_URL, // @phpcs:ignore -- No need to change the class property ); $this->save_data(); return array( 'redirect_url' => add_query_arg( $args, $this->AUTHORIZATION_URL ) ); } return false; } /** * Remove the service account from the database. This cannot be undone. The instance * will no longer be usable after a call to this method. * * @since 1.1.0 */ abstract public function delete(); /** * Get the form fields to show in the WP Dashboard for this service's accounts. * * @since 1.1.0 * * @return array */ abstract public function get_account_fields(); /** * Get an array that maps our data keys to those returned by the 3rd-party service's API. * * @since 1.1.0 * * @param array $keymap A mapping of our data key addresses to those of the service, organized by type/category. * * @return array[] { * * @type array $key_type { * * @type string $our_key_address The corresponding key address on the service. * ... * } * ... * } */ abstract public function get_data_keymap( $keymap = array() ); /** * Get error message for a response that has an ERROR status. If possible the provider's * error message will be returned. Otherwise the HTTP error status description will be returned. * * @return string */ public function get_error_message() { if ( ! empty( $this->data_keys['error'] ) ) { $data = $this->transform_data_to_our_format( $this->response->DATA, 'error' ); return isset( $data['error_message'] ) ? $data['error_message'] : ''; } return $this->response->ERROR_MESSAGE; } /** * Whether or not the current account has been authenticated with the service's API. * * @return bool */ public function is_authenticated() { return isset( $this->data['is_authorized'] ) && in_array( $this->data['is_authorized'], array( true, 'true' ) ); } /** * Makes a remote request using the current {@link self::http->request}. Automatically * handles custom headers and OAuth when applicable. */ public function make_remote_request() { if ( ! empty( $this->custom_headers ) ) { $this->http->request->HEADERS = array_merge( $this->http->request->HEADERS, $this->custom_headers ); } if ( $this->uses_oauth ) { $oauth2 = '2.0' === $this->oauth_version; $this->http->request = $this->OAuth_Helper->prepare_oauth_request( $this->http->request, $oauth2 ); } else if ( $this->http_auth ) { $this->_add_http_auth_header_to_request(); } $this->request = $this->http->request; $this->http->make_remote_request(); $this->response = $this->http->response; } /** * Convenience accessor for {@link self::http->prepare_request()} * * @param string $url * @param string $method * @param bool $is_auth * @param mixed $body * @param bool $json_body * @param bool $ssl_verify */ public function prepare_request( $url, $method = 'GET', $is_auth = false, $body = null, $json_body = false, $ssl_verify = true ) { $this->http->prepare_request( $url, $method, $is_auth, $body, $json_body, $ssl_verify ); $this->request = $this->http->request; } /** * Save this service's data to the database. * * @return mixed */ abstract public function save_data(); /** * Set the account name for the instance. Changing the accounts name affects the * value of {@link self::data}. * * @param string $name */ abstract public function set_account_name( $name ); /** * Transforms an array from our data format to that of the service provider. * * @param array $data The data to be transformed. * @param string $key_type The type of data. This corresponds to the key_type in {@link self::data_keys}. * @param array $exclude_keys Keys that should be excluded from the transformed data. * * @return array */ public function transform_data_to_our_format( $data, $key_type, $exclude_keys = array() ) { if ( ! isset( $this->data_keys[ $key_type ] ) ) { return array(); } return self::$_->array_transform( $data, $this->data_keys[ $key_type ], '<-', $exclude_keys ); } /** * Transforms an array from the service provider's data format to our data format. * * @param array $data The data to be transformed. * @param string $key_type The type of data. This corresponds to the key_type in {@link self::data_keys}. * @param array $exclude_keys Keys that should be excluded from the transformed data. * * @return array */ public function transform_data_to_provider_format( $data, $key_type, $exclude_keys = array() ) { if ( ! isset( $this->data_keys[ $key_type ] ) ) { return array(); } return self::$_->array_transform( $data, $this->data_keys[ $key_type ], '->', $exclude_keys ); } } PKE\K\components/api/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\~8gg components/api/ElegantThemes.phpnu[username = sanitize_text_field( $username ); $this->api_key = sanitize_text_field( $api_key ); } /** * Decorate a payload array with common data. * * @since 3.10 * * @param array $payload * * @return array */ protected function _get_decorated_payload( $payload ) { if ( ! isset( $payload['username'] ) ) { $payload['username'] = $this->username; } if ( ! isset( $payload['api_key'] ) ) { $payload['api_key'] = $this->api_key; } return $payload; } /** * Decorate request options array with common options. * * @since 3.10 * * @param array $options * * @return array */ protected function _get_decorated_request_options( $options = array() ) { global $wp_version; $options = array_merge( array( 'timeout' => 10, 'user-agent' => 'WordPress/' . $wp_version . '; Elegant Themes/' . ET_CORE_VERSION . '; ' . home_url( '/' ), ), $options ); return $options; } /** * Parse a response from the API. * * @since 3.10 * * @param array|WP_Error $response * * @return object|WP_Error */ protected function _parse_response( $response ) { if ( is_wp_error( $response ) ) { return $response; } $response_body = trim( wp_remote_retrieve_body( $response ) ); if ( '' === $response_body ) { return new WP_Error( 'et_unknown', esc_html__( 'An unknown error has occurred. Please try again later.', 'et-core' ) ); } $credentials_errors = array( 'Username is not set.', 'Subscription is not active', ); if ( in_array( $response_body, $credentials_errors ) ) { return new WP_Error( 'et_invalid_api_credentials', esc_html__( 'Invalid Username and/or API Key provided.', 'et-core' ) ); } return maybe_unserialize( $response_body ); } /** * Get the full API endpoint. * * @since 3.10 * * @param string $endpoint "api" or "api_downloads" * * @return string */ protected function _get_endpoint( $endpoint = 'api' ) { $allowed_endpoints = array( 'api', 'api_downloads' ); $suffix = '.php'; if ( ! in_array( $endpoint, $allowed_endpoints ) ) { $endpoint = $allowed_endpoints[0]; } return esc_url_raw( $this->api_url . $endpoint . $suffix ); } /** * Submit a GET request to the API. * * @since 3.10 * * @param array $payload * @param string $endpoint * * @return object|WP_Error */ protected function _get( $payload, $endpoint = 'api' ) { $payload = $this->_get_decorated_payload( $payload ); $options = $this->_get_decorated_request_options(); $url = esc_url_raw( add_query_arg( $payload, $this->_get_endpoint( $endpoint ) ) ); $response = wp_remote_get( $url, $options ); return $this->_parse_response( $response ); } /** * Submit a POST request to the API. * * @since 3.10 * * @param array $payload * @param string $endpoint * * @return object|WP_Error */ protected function _post( $payload, $endpoint = 'api' ) { $payload = $this->_get_decorated_payload( $payload ); $options = $this->_get_decorated_request_options( array( 'body' => $payload, ) ); $response = wp_remote_post( $this->_get_endpoint( $endpoint ), $options ); return $this->_parse_response( $response ); } /** * Check if a product is available. * * @since 3.10 * * @param string $product_name * @param string $version * * @return bool|WP_Error */ public function is_product_available( $product_name, $version ) { $response = $this->_get( array( 'api_update' => 1, 'action' => 'check_version_status', 'product' => $product_name, 'version' => $version, ) ); if ( is_wp_error( $response ) ) { return $response; } if ( ! is_array( $response ) ) { return new WP_Error( 'et_unknown', esc_html__( 'An unexpected response was received from the version server. Please try again later.', 'et-core' ) ); } switch ( $response['status'] ) { case 'not_available': return new WP_Error( 'et_version_rollback_not_available', sprintf( esc_html__( 'The previously used version of %1$s does not support version rollback.', 'et-core' ), esc_html( $product_name ) ) ); case 'blocklisted': return new WP_Error( 'et_version_rollback_blocklisted', et_get_safe_localization( sprintf( __( 'For privacy and security reasons, you cannot rollback to Version %1$s.', 'et-core' ), esc_html( $version ) ) ) ); case 'available': return true; } return new WP_Error( 'et_unknown', esc_html__( 'An unknown error has occurred. Please try again later.', 'et-core' ) ); } /** * Get a product download url for a specific version, if available. * * @since 3.10 * * @param string $product_name * @param string $version * * @return string|WP_Error */ public function get_download_url( $product_name, $version ) { $payload = $this->_get_decorated_payload( array( 'api_update' => 1, 'theme' => $product_name, 'version' => $version, ) ); return esc_url_raw( add_query_arg( $payload, $this->_get_endpoint( 'api_downloads' ) ) ); } } endif; PKE\components/api/README.mdnu[## Core API Component Group This directory contains components that facilitate interacting with 3rd-party REST APIs. ### What's Inside |File|Name|Description| |:--------|:----------|:----------| |**email**|**ET_Core_API_Email**|Email marketing service providers| |**social**|**ET_Core_API_Social**|Social networks| |Service.php|ET_Core_API_Service|Base class for all API components| |OAuthHelper.php|ET_Core_API_OAuthHelper|Handles OAuth authorization flow| > ***Note:*** Component groups are in **bold**. ### Class Hierarchy

    PKE\kY?? components/api/spam/Provider.phpnu[account_name || ! is_string( $this->account_name ) ) { return array(); } $provider = sanitize_text_field( $this->slug ); $account = sanitize_text_field( $this->account_name ); if ( ! isset( $options['accounts'][ $provider ][ $account ] ) ) { $options['accounts'][ $provider ][ $account ] = array(); update_option( 'et_core_api_spam_options', $options ); } return $options['accounts'][ $provider ][ $account ]; } /** * Returns whether or not an account exists in the database. * * @since 4.0.7 * * @param string $provider * @param string $account_name * * @return bool */ public static function account_exists( $provider, $account_name ) { $all_accounts = self::get_accounts(); return isset( $all_accounts[ $provider ][ $account_name ] ); } /** * @since 4.0.7 * * @inheritDoc */ public function delete() { self::remove_account( $this->slug, $this->account_name ); $this->account_name = ''; $this->_get_data(); } /** * Retrieves the email accounts data from the database. * * @since 4.0.7 * * @return array */ public static function get_accounts() { $options = (array) get_option( 'et_core_api_spam_options' ); return isset( $options['accounts'] ) ? $options['accounts'] : array(); } /** * @since 4.0.7 * * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { return $keymap; } abstract public function is_enabled(); /** * Remove an account * * @since 4.0.7 * * @param string $provider * @param string $account_name */ public static function remove_account( $provider, $account_name ) { $options = (array) get_option( 'et_core_api_spam_options' ); unset( $options['accounts'][ $provider ][ $account_name ] ); update_option( 'et_core_api_spam_options', $options ); } /** * @since 4.0.7 * * @inheritDoc */ public function save_data() { self::update_account( $this->slug, $this->account_name, $this->data ); } /** * @since 4.0.7 * * @inheritDoc */ public function set_account_name( $name ) { $this->account_name = $name; $this->data = $this->_get_data(); } /** * Remove keys with brackets. * * Fixing my errors is no walk in the park; it's more like a hike up Mt. * * @param array $data Options array. * @return void */ public static function remove_keys_with_brackets( &$data ) { foreach ( $data as $key => &$value ) { if ( is_array( $value ) ) { self::remove_keys_with_brackets( $value ); } if ( strpos( $key, '[' ) === 0 && strpos( $key, ']' ) === strlen( $key ) - 1 ) { unset( $data[ $key ] ); } } } /** * Updates the data for a provider account. * * @since 4.0.7 * * @param string $provider The provider's slug. * @param string $account The account name. * @param array $data The new data for the account. */ public static function update_account( $provider, $account, $data ) { if ( empty( $account ) || empty( $provider ) ) { return; } $options = (array) get_option( 'et_core_api_spam_options' ); $provider = sanitize_text_field( $provider ); $account = sanitize_text_field( $account ); self::remove_keys_with_brackets( $options ); self::$_->array_update( $options, "accounts.$provider.$account", $data ); update_option( 'et_core_api_spam_options', $options ); } abstract public function verify_form_submission(); } PKE\$!components/api/spam/ReCaptcha.phpnu[_add_actions_and_filters(); } protected function _add_actions_and_filters() { if ( ! is_admin() && ! et_core_is_fb_enabled() ) { add_action( 'wp_enqueue_scripts', array( $this, 'action_wp_enqueue_scripts' ) ); } } public function action_wp_enqueue_scripts() { if ( ! $this->is_enabled() ) { return; } /** * reCAPTCHA v3 actions may only contain alphanumeric characters and slashes/underscore. * https://developers.google.com/recaptcha/docs/v3#actions * * Replace all non-alphanumeric characters with underscore. * Ex: '?page_id=254980' => '_page_id_254980' */ $action = preg_replace( '/[^A-Za-z0-9]/', '_', basename( get_the_permalink() ) ); $deps = array( 'jquery', 'es6-promise', 'et-recaptcha-v3' ); wp_register_script( 'et-recaptcha-v3', "https://www.google.com/recaptcha/api.js?render={$this->data['site_key']}", array(), ET_CORE_VERSION, true ); wp_register_script( 'es6-promise', ET_CORE_URL . 'admin/js/es6-promise.auto.min.js', array(), ET_CORE_VERSION, true ); wp_enqueue_script( 'et-core-api-spam-recaptcha', ET_CORE_URL . 'admin/js/recaptcha.js', $deps, ET_CORE_VERSION, true ); wp_localize_script( 'et-core-api-spam-recaptcha', 'et_core_api_spam_recaptcha', array( 'site_key' => empty( $this->data['site_key'] ) ? '' : $this->data['site_key'], 'page_action' => array( 'action' => $action ), ) ); } public function is_enabled() { $has_recaptcha_module = true; if ( class_exists( 'ET_Dynamic_Assets' ) ) { $et_dynamic_module_framework = et_builder_dynamic_module_framework(); $is_dynamic_framework_enabled = et_builder_is_frontend() && 'on' === $et_dynamic_module_framework; $is_dynamic_css_enabled = et_builder_is_frontend() && et_use_dynamic_css(); if ( $is_dynamic_framework_enabled && $is_dynamic_css_enabled ) { $et_dynamic_assets = ET_Dynamic_Assets::init(); $saved_shortcodes = $et_dynamic_assets->get_saved_page_shortcodes(); $recaptcha_modules = array( 'et_pb_contact_form', 'et_pb_signup' ); $has_recaptcha_module = ! empty( array_intersect( $saved_shortcodes, $recaptcha_modules ) ); } } $has_key = isset( $this->data['site_key'], $this->data['secret_key'] ) && et_()->all( array( $this->data['site_key'], $this->data['secret_key'] ) ); return $has_key && $has_recaptcha_module; } /** * Verify a form submission. * * @since 4.0.7 * * @global $_POST['token'] * * @return mixed[]|string $result { * Interaction Result * * @type bool $success Whether or not the request was valid for this site. * @type int $score Score for the request (0 < score < 1). * @type string $action Action name for this request (important to verify). * @type string $challenge_ts Timestamp of the challenge load (ISO format yyyy-MM-ddTHH:mm:ssZZ). * @type string $hostname Hostname of the site where the challenge was solved. * @type string[] $error-codes Optional * } */ public function verify_form_submission() { $args = array( 'secret' => $this->data['secret_key'], 'response' => et_()->array_get_sanitized( $_POST, 'token' ), 'remoteip' => et_core_get_ip_address(), ); $this->prepare_request( $this->BASE_URL, 'POST', false, $args ); $this->make_remote_request(); return $this->response->ERROR ? $this->response->ERROR_MESSAGE : $this->response->DATA; } /** * @inheritDoc */ public function get_account_fields() { return array( 'site_key' => array( 'label' => esc_html__( 'Site Key (v3)', 'et_core' ), ), 'secret_key' => array( 'label' => esc_html__( 'Secret Key (v3)', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { return array( 'ip_address' => 'remoteip', 'response' => 'response', 'secret_key' => 'secret', ); } } PKE\K\components/api/spam/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\>*!components/api/spam/Providers.phpnu[_initialize(); } } protected function _initialize() { self::$_ = ET_Core_Data_Utils::instance(); self::$_metadata = et_core_get_components_metadata(); $third_party_providers = et_core_get_third_party_components( 'api/spam' ); $load_fields = is_admin() || et_core_is_saving_builder_modules_cache() || et_core_is_fb_enabled() || isset( $_GET['et_fb'] ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification $all_names = array( 'official' => self::$_metadata['groups']['api/spam']['members'], 'third-party' => array_keys( $third_party_providers ), ); $_names_by_slug = array(); foreach ( $all_names as $provider_type => $provider_names ) { $_names_by_slug[ $provider_type ] = array(); foreach ( $provider_names as $provider_name ) { if ( 'Fields' === $provider_name || self::$_->includes( $provider_name, 'Provider' ) ) { continue; } if ( 'official' === $provider_type ) { $class_name = self::$_metadata[ $provider_name ]; $provider_slug = self::$_metadata[ $class_name ]['slug']; $provider = $load_fields ? new $class_name( 'ET_Core', '' ) : null; } else { $provider = $third_party_providers[ $provider_name ]; $provider_slug = is_object( $provider ) ? $provider->slug : ''; } if ( ! $provider_slug ) { continue; } $_names_by_slug[ $provider_type ][ $provider_slug ] = $provider_name; if ( $load_fields && is_object( $provider ) ) { self::$_fields[ $provider_slug ] = $provider->get_account_fields(); } } } /** * Filters the enabled anti-spam providers. * * @since 4.0.7 * * @param array[] $_names_by_slug { * * @type string[] $provider_type { * * @type string $slug Provider name * } * } */ self::$_names_by_slug = apply_filters( 'et_core_api_spam_enabled_providers', $_names_by_slug ); foreach ( array_keys( $all_names ) as $provider_type ) { self::$_names[ $provider_type ] = array_values( self::$_names_by_slug[ $provider_type ] ); self::$_slugs[ $provider_type ] = array_keys( self::$_names_by_slug[ $provider_type ] ); } } /** * Returns the spam provider accounts array from core. * * @since 4.0.7 * * @return array|mixed */ public function accounts() { return ET_Core_API_Spam_Provider::get_accounts(); } /** * @see {@link \ET_Core_API_Spam_Provider::account_exists()} */ public function account_exists( $provider, $account_name ) { return ET_Core_API_Spam_Provider::account_exists( $provider, $account_name ); } public function account_fields( $provider = 'all' ) { if ( 'all' !== $provider ) { if ( isset( self::$_fields[ $provider ] ) ) { return self::$_fields[ $provider ]; } if ( ! is_admin() && et_core_is_saving_builder_modules_cache() ) { // Need to initialize again because et_core_is_saving_builder_modules_cache // can't be called too early. $this->_initialize(); return et_()->array_get( self::$_fields, $provider, array() ); } return array(); } return self::$_fields; } /** * Get class instance for a provider. Instance will be created if necessary. * * @param string $name_or_slug The provider's name or slug. * @param string $account_name The identifier for the desired account with the provider. * @param string $owner The owner for the instance. * * @return ET_Core_API_Spam_Provider|bool The provider instance or `false` if not found. */ public function get( $name_or_slug, $account_name, $owner = 'ET_Core' ) { $name_or_slug = str_replace( ' ', '', $name_or_slug ); $is_official = isset( self::$_metadata[ $name_or_slug ] ); if ( ! $is_official && ! $this->is_third_party( $name_or_slug ) ) { return false; } if ( ! in_array( $name_or_slug, array_merge( self::names(), self::slugs() ) ) ) { return false; } // Make sure we have the component name if ( $is_official ) { $class_name = self::$_metadata[ $name_or_slug ]; $name = self::$_metadata[ $class_name ]['name']; } else { $components = et_core_get_third_party_components( 'api/spam' ); if ( ! $name = array_search( $name_or_slug, self::$_names_by_slug['third-party'] ) ) { $name = $name_or_slug; } } if ( ! isset( self::$providers[ $name ][ $owner ] ) ) { self::$providers[ $name ][ $owner ] = $is_official ? new $class_name( $owner, $account_name ) : $components[ $name ]; } return self::$providers[ $name ][ $owner ]; } public static function instance() { if ( null === self::$_instance ) { self::$_instance = new self; } return self::$_instance; } public function is_third_party( $name_or_slug ) { $is_third_party = in_array( $name_or_slug, self::$_names['third-party'] ); return $is_third_party ? $is_third_party : in_array( $name_or_slug, self::$_slugs['third-party'] ); } /** * Returns the names of available providers. List can optionally be filtered. * * @since 4.0.7 * * @param string $type The component type to include ('official'|'third-party'|'all'). Default is 'all'. * * @return array */ public static function names( $type = 'all' ) { if ( 'all' === $type ) { $names = array_merge( self::$_names['third-party'], self::$_names['official'] ); } else { $names = self::$_names[ $type ]; } return $names; } /** * Returns an array mapping the slugs of available providers to their names. * * @since 4.0.7 * * @param string $type The component type to include ('official'|'third-party'|'all'). Default is 'all'. * * @return array */ public function names_by_slug( $type = 'all' ) { if ( 'all' === $type ) { $names_by_slug = array_merge( self::$_names_by_slug['third-party'], self::$_names_by_slug['official'] ); } else { $names_by_slug = self::$_names_by_slug[ $type ]; } return $names_by_slug; } /** * @see {@link \ET_Core_API_Spam_Provider::remove_account()} */ public function remove_account( $provider, $account_name ) { ET_Core_API_Spam_Provider::remove_account( $provider, $account_name ); } /** * Returns the slugs of available providers. List can optionally be filtered. * * @since 4.0.7 * * @param string $type The component type to include ('official'|'third-party'|'all'). Default is 'all'. * * @return array */ public static function slugs( $type = 'all' ) { if ( 'all' === $type ) { $names = array_merge( self::$_slugs['third-party'], self::$_slugs['official'] ); } else { $names = self::$_slugs[ $type ]; } return $names; } /** * @since 4.0.7 * * @see {@link \ET_Core_API_Spam_Provider::update_account()} */ public function update_account( $provider, $account, $data ) { ET_Core_API_Spam_Provider::update_account( $provider, $account, $data ); } } PKE\sL^ ^ components/api/spam/init.phpnu[get( 'recaptcha', '' ); } } endif; if ( ! function_exists('et_builder_spam_add_account' ) ): function et_core_api_spam_add_account( $name_or_slug, $account, $api_key ) { et_core_security_check(); if ( empty( $name_or_slug ) || empty( $account ) ) { return __( 'ERROR: Invalid arguments.', 'et_core' ); } $providers = ET_Core_API_Spam_Providers::instance(); $provider = $providers->get( $name_or_slug, $account, 'builder' ); if ( ! $provider ) { return ''; } if ( is_array( $api_key ) ) { foreach ( $api_key as $field_name => $value ) { $provider->data[ $field_name ] = sanitize_text_field( $value ); } } else if ( '' !== $api_key ) { $provider->data['api_key'] = sanitize_text_field( $api_key ); } $provider->save_data(); return 'success'; } endif; if ( ! function_exists( 'et_core_api_spam_find_provider_account' ) ): function et_core_api_spam_find_provider_account() { $spam_providers = ET_Core_API_Spam_Providers::instance(); if ( $accounts = $spam_providers->accounts() ) { $enabled_account = ''; $provider = ''; foreach ( $accounts as $provider_slug => $provider_accounts ) { if ( empty( $provider_accounts ) ) { continue; } foreach ( $provider_accounts as $account_name => $account ) { if ( isset( $account['site_key'], $account['secret_key'] ) ) { $provider = $provider_slug; $enabled_account = $account_name; break; } } } if ( $provider && $enabled_account ) { return $spam_providers->get( $provider, $enabled_account ); } } return false; } endif; if ( ! function_exists( 'et_core_api_spam_remove_account' ) ): /** * Delete an existing provider account. * * @since 4.0.7 * * @param string $name_or_slug The provider name or slug. * @param string $account The account name. */ function et_core_api_spam_remove_account( $name_or_slug, $account ) { et_core_security_check(); if ( empty( $name_or_slug ) || empty( $account ) ) { return; } $providers = ET_Core_API_Spam_Providers::instance(); if ( $provider = $providers->get( $name_or_slug, $account ) ) { $provider->delete(); } } endif; PKE\?Jcomponents/api/init.phpnu[accounts_url = "{$this->BASE_URL}/accounts"; } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $this->prepare_request( $list['custom_fields_collection_link'] ); return parent::_fetch_custom_fields( $list_id, $list ); } protected function _get_lists_collection_url() { $this->prepare_request( $this->accounts_url ); $this->make_remote_request(); $url = ''; if ( ! $this->response->ERROR && ! empty( $this->response->DATA['entries'][0]['lists_collection_link'] ) ) { $url = $this->response->DATA['entries'][0]['lists_collection_link']; } return $url; } protected static function _parse_ID( $ID ) { $values = explode( '|', $ID ); return ( count( $values ) === 6 ) ? $values : null; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } $list_id = $args['list_id']; $field_name = self::$_->array_get( $this->data, "lists.{$list_id}.custom_fields.{$field_id}.name" ); self::$_->array_set( $args, "custom_fields.{$field_name}", $value ); } return $args; } /** * Uses the app's authorization code to get an access token */ public function authenticate() { if ( empty( $this->data['api_key'] ) ) { return false; } $key_parts = self::_parse_ID( $this->data['api_key'] ); if ( null === $key_parts ) { return false; } list( $consumer_key, $consumer_secret, $request_token, $request_secret, $verifier ) = $key_parts; if ( ! $verifier ) { return false; } $this->data['consumer_key'] = $consumer_key; $this->data['consumer_secret'] = $consumer_secret; $this->data['access_key'] = $request_token; $this->data['access_secret'] = $request_secret; $this->oauth_verifier = $verifier; // AWeber returns oauth access key in url query format :face_with_rolling_eyes: $this->http->expects_json = false; return parent::authenticate(); } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'Authorization Code', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_error_message() { $error_message = parent::get_error_message(); return preg_replace('/https.*/m', '', $error_message ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'total_subscribers', ), 'subscriber' => array( 'name' => 'name', 'email' => 'email', 'ad_tracking' => 'ad_tracking', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'error.message', ), 'custom_field' => array( 'field_id' => 'id', 'name' => 'name', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { $needs_to_authenticate = ! $this->is_authenticated() || ! $this->_initialize_oauth_helper(); if ( $needs_to_authenticate && ! $this->authenticate() ) { if ( empty( $this->response->DATA ) ) { return ''; } $this->response->DATA = json_decode( $this->response->DATA, true ); return $this->get_error_message(); } $this->http->expects_json = true; $this->LISTS_URL = $this->_get_lists_collection_url(); if ( empty( $this->LISTS_URL ) ) { return ''; } $this->response_data_key = 'entries'; return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $lists_url = $this->_get_lists_collection_url(); $url = "{$lists_url}/{$args['list_id']}/subscribers"; $ip_address = 'true' === self::$_->array_get( $args, 'ip_address', 'true' ); $params = $this->_process_custom_fields( $args ); $params = $this->transform_data_to_provider_format( $params, 'subscriber' ); $params = array_merge( $params, array( 'ws.op' => 'create', 'ip_address' => $ip_address ? et_core_get_ip_address() : '0.0.0.0', 'misc_notes' => $this->SUBSCRIBED_VIA, ) ); // There is a bug in AWeber some characters not encoded properly on AWeber side when sending data in x-www-form-urlencoded format so use json instead $this->prepare_request( $url, 'POST', false, $params, true ); $this->request->HEADERS['Content-Type'] = 'application/json'; return parent::subscribe( $params, $url ); } } PKE\.^7(components/api/email/CampaignMonitor.phpnu[ 'api_key', 'password' => '-', ); /** * @inheritDoc */ public $name = 'CampaignMonitor'; /** * @inheritDoc */ public $name_field_only = true; /** * @inheritDoc */ public $slug = 'campaign_monitor'; /** * @inheritDoc * @internal If true, oauth endpoints properties must also be defined. */ public $uses_oauth = false; public function __construct( $owner, $account_name, $api_key = '' ) { parent::__construct( $owner, $account_name, $api_key ); $this->http_auth['password'] = $owner; } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $this->prepare_request( "{$this->BASE_URL}/lists/{$list_id}/customfields.json" ); $this->make_remote_request(); $result = array(); if ( $this->response->ERROR ) { et_debug( $this->get_error_message() ); return $result; } foreach ( $this->response->DATA as &$custom_field ) { $custom_field = $this->transform_data_to_our_format( $custom_field, 'custom_field' ); $custom_field['field_id'] = ltrim( rtrim( $custom_field['field_id'], ']' ), '[' ); } $fields = array(); foreach ( $this->response->DATA as $field ) { $field_id = $field['field_id']; $type = self::$_->array_get( $field, 'type', 'any' ); $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'any' ); $fields[ $field_id ] = $field; } return $fields; } protected function _get_clients() { $url = "{$this->BASE_URL}/clients.json"; $this->prepare_request( $url ); $this->make_remote_request(); if ( $this->response->ERROR ) { return $this->get_error_message(); } return (array) $this->response->DATA; } protected function _get_subscriber_counts() { $subscriber_lists = $this->_process_subscriber_lists( $this->response->DATA ); $with_counts = array(); foreach ( $subscriber_lists as $subscriber_list ) { $list_id = $subscriber_list['list_id']; $with_counts[ $list_id ] = $subscriber_list; $url = "{$this->BASE_URL}/lists/{$list_id}/stats.json"; $this->prepare_request( $url ); $this->make_remote_request(); if ( $this->response->ERROR ) { continue; } if ( isset( $this->response->DATA['TotalActiveSubscribers'] ) ) { $with_counts[ $list_id ]['subscribers_count'] = $this->response->DATA['TotalActiveSubscribers']; } else { $with_counts[ $list_id ]['subscribers_count'] = 0; } usleep( 500000 ); // 0.5 seconds } return $with_counts; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields_unprocessed = $args['custom_fields']; unset( $args['custom_fields'] ); $fields = array(); foreach ( $fields_unprocessed as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox) foreach ( $value as $selected_option ) { $fields[] = array( 'Key' => $field_id, 'Value' => $selected_option, ); } } else { $fields[] = array( 'Key' => $field_id, 'Value' => $value, ); } } $args['CustomFields'] = $fields; return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'ListID', 'name' => 'Name', 'subscribers_count' => 'TotalActiveSubscribers', ), 'subscriber' => array( 'name' => 'Name', 'email' => 'EmailAddress', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'Message', ), 'custom_field' => array( 'field_id' => 'Key', 'name' => 'FieldName', 'type' => 'DataType', 'options' => 'FieldOptions', ), 'custom_field_type' => array( // Us => Them 'input' => 'Text', 'select' => 'MultiSelectOne', 'checkbox' => 'MultiSelectMany', // Them => Us 'Text' => 'input', 'Number' => 'input', 'Date' => 'input', 'MultiSelectOne' => 'select', 'MultiSelectMany' => 'checkbox', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $clients = $this->_get_clients(); $lists = array(); if ( ! is_array( $clients ) ) { // Request failed with an error, return the error message. return $clients; } foreach ( $clients as $client_info ) { if ( empty( $client_info['ClientID'] ) ) { continue; } $url = "{$this->BASE_URL}/clients/{$client_info['ClientID']}/lists.json"; $this->prepare_request( $url ); parent::fetch_subscriber_lists(); if ( $this->response->ERROR ) { return $this->get_error_message(); } if ( isset( $this->response->DATA ) ) { $with_counts = $this->_get_subscriber_counts(); $lists = $lists + $with_counts; $this->data['is_authorized'] = true; $this->save_data(); } } if ( empty( $this->data['lists'] ) || ! empty( $lists ) ) { $this->data['lists'] = $lists; $this->save_data(); } return $this->is_authenticated() ? 'success' : $this->FAILURE_MESSAGE; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $url = "{$this->BASE_URL}/subscribers/{$args['list_id']}.json"; $params = $this->transform_data_to_provider_format( $args, 'subscriber' ); $params = $this->_process_custom_fields( $params ); $params['CustomFields'][] = array( 'Key' => 'Note', 'Value' => $this->SUBSCRIBED_VIA ); $this->prepare_request( $url, 'POST', false, $params, true ); return parent::subscribe( $params, $url ); } } PKE\,}*}*!components/api/email/Provider.phpnu[service_type = 'email'; parent::__construct( $owner, $account_name, $api_key ); if ( 'builder' === $this->owner ) { $owner = 'Divi Builder'; } else { $owner = ucfirst( $this->owner ); } $this->SUBSCRIBED_VIA = sprintf( '%1$s %2$s.', esc_html__( 'Subscribed via', 'et_core' ), $owner ); /** * Filters the max number of results returned from email API provider per request. * * @since 3.17.2 * * @param int $max_results_count */ $this->COUNT = apply_filters( 'et_core_api_email_max_results_count', 250 ); } /** * Get custom fields for a subscriber list. * * @param int|string $list_id * @param array $list * * @return array */ protected function _fetch_custom_fields( $list_id = '', $list = array() ) { if ( 'dynamic' === $this->custom_fields ) { return array(); } if ( null === $this->request || $this->request->COMPLETE ) { $this->prepare_request( $this->FIELDS_URL ); } $this->make_remote_request(); $result = array(); if ( false !== $this->response_data_key && empty( $this->response_data_key ) ) { // Let child class handle parsing the response data themselves. return $result; } if ( $this->response->ERROR ) { et_debug( $this->get_error_message() ); return $result; } if ( false === $this->response_data_key ) { // The data returned by the service is not nested. $data = $this->response->DATA; } else { // The data returned by the service is nested under a single key. $data = $this->response->DATA[ $this->response_data_key ]; } foreach ( $data as &$custom_field ) { $custom_field = $this->transform_data_to_our_format( $custom_field, 'custom_field' ); } $fields = array(); $field_types = self::$_->array_get( $this->data_keys, 'custom_field_type' ); foreach ( $data as $field ) { $field_id = $field['field_id']; $type = self::$_->array_get( $field, 'type', 'any' ); if ( $field_types && ! isset( $field_types[ $type ] ) ) { // Unsupported field type. Make it 'text' instead. $type = 'text'; } if ( isset( $field['hidden'] ) && is_string( $field['hidden'] ) ) { $field['hidden'] = 'false' === $field['hidden'] ? false : true; } $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'any' ); $fields[ $field_id ] = $field; } return $fields; } /** * @inheritDoc */ protected function _get_data() { $options = parent::_get_data(); // return empty array in case of empty name if ( '' === $this->account_name || ! is_string( $this->account_name ) ) { return array(); } $provider = sanitize_text_field( $this->slug ); $account = sanitize_text_field( $this->account_name ); if ( ! isset( $options['accounts'][ $provider ][ $account ] ) ) { $options['accounts'][ $provider ][ $account ] = array(); update_option( "et_core_api_email_options", $options ); } return $options['accounts'][ $provider ][ $account ]; } protected function _process_custom_fields( $args ) { return $args; } /** * Processes subscriber lists data from the provider's API and returns only the data we're interested in. * * @since 1.1.0 * * @param array $lists Subscriber lists data to process. * * @return array */ protected function _process_subscriber_lists( $lists ) { $id_key = $this->data_keys['list']['list_id']; $result = array(); foreach ( (array) $lists as $list ) { if ( ! is_array( $list ) ) { $list = (array) $list; } if ( ! isset( $list[ $id_key ] ) ) { continue; } $id = $list[ $id_key ]; $result[ $id ] = $this->transform_data_to_our_format( $list, 'list' ); if ( ! array_key_exists( 'subscribers_count', $result[ $id ] ) ) { $result[ $id ]['subscribers_count'] = 0; } $get_custom_fields = $this->custom_fields && 'list' === $this->custom_fields_scope; if ( $get_custom_fields && $custom_fields = $this->_fetch_custom_fields( $id, $list ) ) { $result[ $id ]['custom_fields'] = $custom_fields; } } return $result; } /** * Returns whether or not an account exists in the database. * * @param string $provider * @param string $account_name * * @return bool */ public static function account_exists( $provider, $account_name ) { $all_accounts = self::get_accounts(); return isset( $all_accounts[ $provider ][ $account_name ] ); } /** * @inheritDoc */ public function delete() { self::remove_account( $this->slug, $this->account_name ); $this->account_name = ''; $this->_get_data(); } /** * Retrieves the email accounts data from the database. * * @return array */ public static function get_accounts() { $options = (array) get_option( 'et_core_api_email_options' ); return isset( $options['accounts'] ) ? $options['accounts'] : array(); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { return $keymap; } /** * Retrieves the subscriber lists for the account assigned to the current instance. * * @return string 'success' if successful, an error message otherwise. */ public function fetch_subscriber_lists() { if ( null === $this->request || $this->request->COMPLETE ) { $this->prepare_request( $this->LISTS_URL ); } $this->make_remote_request(); $result = 'success'; if ( false !== $this->response_data_key && empty( $this->response_data_key ) ) { // Let child class handle parsing the response data themselves. return ''; } if ( $this->response->ERROR ) { return $this->get_error_message(); } if ( false === $this->response_data_key ) { // The data returned by the service is not nested. $data = $this->response->DATA; } else { // The data returned by the service is nested under a single key. $data = $this->response->DATA[ $this->response_data_key ]; } if ( ! empty( $data ) ) { $this->data['lists'] = $this->_process_subscriber_lists( $data ); $this->data['is_authorized'] = true; $list = is_array( $data ) ? array_shift( $data ) : array(); if ( $this->custom_fields && 'account' === $this->custom_fields_scope ) { $this->data['custom_fields'] = $this->_fetch_custom_fields( '', $list ); } $this->save_data(); } return $result; } /** * Remove an account * * @param $provider * @param $account_name */ public static function remove_account( $provider, $account_name ) { $options = (array) get_option( 'et_core_api_email_options' ); unset( $options['accounts'][ $provider ][ $account_name ] ); update_option( 'et_core_api_email_options', $options ); } /** * @inheritDoc */ public function save_data() { self::update_account( $this->slug, $this->account_name, $this->data ); } /** * @inheritDoc */ public function set_account_name( $name ) { $this->account_name = $name; $this->data = $this->_get_data(); } /** * Makes an HTTP POST request to add a subscriber to a list. * * @param string[] $args Data for the POST request. * @param string $url The URL for the POST request. Optional when called on child classes. * * @return string 'success' if successful, an error message otherwise. */ public function subscribe( $args, $url = '' ) { if ( null === $this->request || $this->request->COMPLETE ) { if ( ! in_array( 'ip_address', $args ) || 'true' === $args['ip_address'] ) { $args['ip_address'] = et_core_get_ip_address(); } else if ( 'false' === $args['ip_address'] ) { $args['ip_address'] = '0.0.0.0'; } $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); if ( $this->custom_fields ) { $args = $this->_process_custom_fields( $args ); } $this->prepare_request( $url, 'POST', false, $args ); } else if ( $this->request->JSON_BODY && ! is_string( $this->request->BODY ) && ! $this->uses_oauth ) { $this->request->BODY = json_encode( $this->request->BODY ); } else if ( is_array( $this->request->BODY ) ) { $this->request->BODY = array_merge( $this->request->BODY, $args ); } else if ( ! $this->request->JSON_BODY ) { $this->request->BODY = $args; } $this->make_remote_request(); return $this->response->ERROR ? $this->get_error_message() : 'success'; } /** * Updates the data for a provider account. * * @param string $provider The provider's slug. * @param string $account The account name. * @param array $data The new data for the account. */ public static function update_account( $provider, $account, $data ) { $options = (array) get_option( 'et_core_api_email_options' ); $existing_data = array(); if ( empty( $account ) || empty( $provider ) ) { return; } $provider = sanitize_text_field( $provider ); $account = sanitize_text_field( $account ); if ( isset( $options['accounts'][ $provider ][ $account ] ) ) { $existing_data = $options['accounts'][ $provider ][ $account ]; } $options['accounts'][ $provider ][ $account ] = array_merge( $existing_data, $data ); update_option( 'et_core_api_email_options', $options ); } } PKE\%44$components/api/email/GetResponse.phpnu[_maybe_set_custom_headers(); } protected function _maybe_set_custom_headers() { if ( empty( $this->custom_headers ) && isset( $this->data['api_key'] ) ) { $this->custom_headers = array( 'X-Auth-Token' => "api-key {$this->data['api_key']}" ); } } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields_unprocessed = $args['custom_fields']; $fields = array(); unset( $args['custom_fields'] ); foreach ( $fields_unprocessed as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); } else { $value = array( $value ); } $fields[] = array( 'customFieldId' => $field_id, 'value' => $value, ); } $args['customFieldValues'] = $fields; return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'name' => 'name', 'list_id' => 'campaignId', 'subscribers_count' => 'totalSubscribers', ), 'subscriber' => array( 'name' => 'name', 'email' => 'email', 'list_id' => 'campaign.campaignId', 'ip_address' => 'ipAddress', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'message', ), 'custom_field' => array( 'field_id' => 'customFieldId', 'name' => 'name', 'type' => 'fieldType', 'options' => 'values', 'hidden' => 'hidden', ), 'custom_field_type' => array( // Us <=> Them 'textarea' => 'textarea', 'radio' => 'radio', 'checkbox' => 'checkbox', // Us => Them 'input' => 'text', 'select' => 'single_select', // Them => Us 'text' => 'input', 'single_select' => 'select', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $this->_maybe_set_custom_headers(); $this->response_data_key = false; return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $ip_address = 'true' === self::$_->array_get( $args, 'ip_address', 'true' ) ? et_core_get_ip_address() : '0.0.0.0'; $args['ip_address'] = $ip_address; $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); $args = $this->_process_custom_fields( $args ); $args['note'] = $this->SUBSCRIBED_VIA; $args['dayOfCycle'] = 0; if ( empty( $args['name'] ) ) { unset( $args['name'] ); } $this->prepare_request( $this->SUBSCRIBE_URL, 'POST', false, $args ); return parent::subscribe( $args, $this->SUBSCRIBE_URL ); } } PKE\fzR>R>components/api/email/Fields.phpnu[names_by_slug( 'all', 'custom_fields' ) ); $custom_fields_data = self::$_providers->custom_fields_data(); $fields = array(); if ( 'bloom' === self::$owner ) { $fields = array( 'use_custom_fields' => array( 'label' => esc_html__( 'Use Custom Fields', 'et_core' ), 'type' => 'yes_no_button', 'options' => array( 'on' => esc_html__( 'Yes', 'et_core' ), 'off' => esc_html__( 'No', 'et_core' ), ), 'default' => 'off', 'show_if' => array( 'email_provider' => $custom_fields_support, ), 'allow_dynamic' => array_keys( self::$_providers->names_by_slug( 'all', 'dynamic_custom_fields' ) ), 'description' => esc_html__( 'Enable this option to use custom fields in your opt-in form.', 'et_core' ), ), 'custom_fields' => array( 'type' => 'sortable_list', 'label' => '', 'default' => '[]', ), 'editing_field' => array( 'type' => 'skip', 'default' => 'off', ), ); } foreach ( $custom_fields_data as $provider => $accounts ) { foreach ( $accounts as $account => $lists ) { $account_name = str_replace( ' ', '', strtolower( $account ) ); $key = "predefined_field_{$provider}_{$account_name}"; if ( isset( $lists['custom_fields'] ) ) { // Custom fields are per account $fields[ $key ] = self::_predefined_custom_field_select( $lists['custom_fields'], $provider, $account ); continue; } foreach ( $lists as $list_id => $custom_fields ) { // Custom fields are per list $key = "predefined_field_{$provider}_{$account_name}_{$list_id}"; $fields[ $key ] = self::_predefined_custom_field_select( $custom_fields, $provider, $account, $list_id ); } } } $labels = array( 'link_url' => esc_html__( 'Link URL', 'et_core' ), 'link_text' => esc_html__( 'Link Text', 'et_core' ), 'link_cancel' => esc_html__( 'Discard Changes', 'et_core' ), 'link_save' => esc_html__( 'Save Changes', 'et_core' ), 'link_settings' => esc_html__( 'Option Link', 'et_core' ), ); $fields = array_merge( $fields, array( 'predefined_field' => array( 'type' => 'skip', 'default' => 'none', ), 'field_id' => array( 'label' => esc_html__( 'ID', 'et_core' ), 'type' => 'text', 'default' => '', // <--- Intentional 'description' => esc_html__( 'Define a unique ID for this field. You should use only English characters without special characters or spaces.', 'et_core' ), 'toggle_slug' => 'main_content', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), ), 'field_title' => array( 'label' => esc_html__( 'Name', 'et_core' ), 'type' => 'text', 'description' => esc_html__( 'Set the label that will appear above this field in the opt-in form.', 'et_core' ), 'toggle_slug' => 'main_content', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), 'readonly_if_not' => array( $readonly_dependency => array( 'getresponse', 'sendinblue', 'constant_contact', 'fluentcrm' ), ), ), 'field_type' => array( 'label' => esc_html__( 'Type', 'et_core' ), 'type' => 'select', 'default' => 'none', 'option_category' => 'basic_option', 'options' => array( 'none' => esc_html__( 'Choose a field type...', 'et_core' ), 'input' => esc_html__( 'Input Field', 'et_core' ), 'email' => esc_html__( 'Email Field', 'et_core' ), 'text' => esc_html__( 'Textarea', 'et_core' ), 'checkbox' => esc_html__( 'Checkboxes', 'et_core' ), 'radio' => esc_html__( 'Radio Buttons', 'et_core' ), 'select' => esc_html__( 'Select Dropdown', 'et_core' ), ), 'description' => esc_html__( 'Choose the type of field', 'et_core' ), 'toggle_slug' => 'field_options', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), 'readonly_if_not' => array( $readonly_dependency => self::$_any_custom_field_type_support, ), ), 'checkbox_checked' => array( 'label' => esc_html__( 'Checked By Default', 'et_core' ), 'description' => esc_html__( 'If enabled, the check mark will be automatically selected for the visitor. They can still deselect it.', 'et_core' ), 'type' => 'hidden', 'option_category' => 'layout', 'default' => 'off', 'toggle_slug' => 'field_options', 'show_if' => array( 'field_type' => 'checkbox', ), ), 'checkbox_options' => array( 'label' => esc_html__( 'Options', 'et_core' ), 'type' => 'sortable_list', 'checkbox' => true, 'option_category' => 'basic_option', 'toggle_slug' => 'field_options', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), 'readonly_if_not' => array( $readonly_dependency => self::$_any_custom_field_type_support, ), 'show_if' => array( 'field_type' => 'checkbox', ), 'right_actions' => 'move|link|copy|delete', 'right_actions_readonly' => 'move|link', 'labels' => $labels, ), 'radio_options' => array( 'label' => esc_html__( 'Options', 'et_core' ), 'type' => 'sortable_list', 'radio' => true, 'option_category' => 'basic_option', 'toggle_slug' => 'field_options', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), 'readonly_if_not' => array( $readonly_dependency => self::$_any_custom_field_type_support, ), 'show_if' => array( 'field_type' => 'radio', ), 'right_actions' => 'move|link|copy|delete', 'right_actions_readonly' => 'move|link', 'labels' => $labels, ), 'select_options' => array( 'label' => esc_html__( 'Options', 'et_core' ), 'type' => 'sortable_list', 'option_category' => 'basic_option', 'toggle_slug' => 'field_options', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), 'readonly_if_not' => array( $readonly_dependency => self::$_any_custom_field_type_support, ), 'show_if' => array( 'field_type' => 'select', ), 'right_actions' => 'move|copy|delete', 'right_actions_readonly' => 'move', ), 'min_length' => array( 'label' => esc_html__( 'Minimum Length', 'et_core' ), 'description' => esc_html__( 'Leave at 0 to remove restriction', 'et_core' ), 'type' => 'range', 'default' => '0', 'unitless' => true, 'range_settings' => array( 'min' => '0', 'max' => '255', 'step' => '1', ), 'option_category' => 'basic_option', 'toggle_slug' => 'field_options', 'show_if' => array( 'field_type' => 'input', ), ), 'max_length' => array( 'label' => esc_html__( 'Maximum Length', 'et_core' ), 'description' => esc_html__( 'Leave at 0 to remove restriction', 'et_core' ), 'type' => 'range', 'default' => '0', 'unitless' => true, 'range_settings' => array( 'min' => '0', 'max' => '255', 'step' => '1', ), 'option_category' => 'basic_option', 'toggle_slug' => 'field_options', 'show_if' => array( 'field_type' => 'input', ), ), 'allowed_symbols' => array( 'label' => esc_html__( 'Allowed Symbols', 'et_core' ), 'description' => esc_html__( 'You can validate certain types of information by disallowing certain symbols. Symbols added here will prevent the form from being submitted if added by the user.', 'et_core' ), 'type' => 'select', 'default' => 'all', 'options' => array( 'all' => esc_html__( 'All', 'et_core' ), 'letters' => esc_html__( 'Letters Only (A-Z)', 'et_core' ), 'numbers' => esc_html__( 'Numbers Only (0-9)', 'et_core' ), 'alphanumeric' => esc_html__( 'Alphanumeric Only (A-Z, 0-9)', 'et_core' ), ), 'option_category' => 'basic_option', 'toggle_slug' => 'field_options', 'show_if' => array( 'field_type' => 'input', ), ), 'required_mark' => array( 'label' => esc_html__( 'Required Field', 'et_core' ), 'type' => 'yes_no_button', 'option_category' => 'configuration', 'default' => 'on', 'options' => array( 'on' => esc_html__( 'Yes', 'et_core' ), 'off' => esc_html__( 'No', 'et_core' ), ), 'description' => esc_html__( 'Define whether the field should be required or optional', 'et_core' ), 'toggle_slug' => 'field_options', 'show_if_not' => array( 'email_provider' => 'getresponse', ), ), 'hidden' => array( 'label' => esc_html__( 'Hidden Field', 'et_core' ), 'type' => 'yes_no_button', 'option_category' => 'configuration', 'default' => 'off', 'options' => array( 'on' => esc_html__( 'Yes', 'et_core' ), 'off' => esc_html__( 'No', 'et_core' ), ), 'description' => esc_html__( 'Define whether or not the field should be visible.', 'et_core' ), 'toggle_slug' => 'field_options', 'readonly_if' => array( $readonly_dependency => self::$_predefined_custom_field_support, ), 'readonly_if_not' => array( $readonly_dependency => self::$_any_custom_field_type_support, ), ), 'fullwidth_field' => array( 'label' => esc_html__( 'Make Fullwidth', 'et_core' ), 'type' => 'yes_no_button', 'option_category' => 'layout', 'options' => array( 'on' => esc_html__( 'Yes', 'et_core' ), 'off' => esc_html__( 'No', 'et_core' ), ), 'tab_slug' => 'advanced', 'toggle_slug' => 'layout', 'description' => esc_html__( 'If enabled, the field will take 100% of the width of the form, otherwise it will take 50%', 'et_core' ), 'default' => array( 'parent:layout', array( 'left_right' => 'on', 'right_left' => 'on', 'top_bottom' => 'off', 'bottom_top' => 'off', )), ), ) ); if ( 'builder' === self::$owner ) { $fields = array_merge( $fields, array( 'field_background_color' => array( 'label' => esc_html__( 'Field Background Color', 'et_core' ), 'description' => esc_html__( "Pick a color to fill the module's input fields.", 'et_core' ), 'type' => 'color-alpha', 'custom_color' => true, 'toggle_slug' => 'form_field', 'tab_slug' => 'advanced', ), 'conditional_logic' => array( 'label' => esc_html__( 'Enable', 'et_core' ), 'type' => 'yes_no_button', 'option_category' => 'layout', 'default' => 'off', 'options' => array( 'on' => esc_html__( 'Yes', 'et_core' ), 'off' => esc_html__( 'No', 'et_core' ), ), 'description' => et_get_safe_localization( __( "Enabling conditional logic makes this field only visible when any or all of the rules below are fulfilled
    Note: Only fields with an unique and non-empty field ID can be used", 'et_core' ) ), 'toggle_slug' => 'conditional_logic', ), 'conditional_logic_relation' => array( 'label' => esc_html__( 'Relation', 'et_core' ), 'type' => 'yes_no_button', 'option_category' => 'layout', 'options' => array( 'on' => esc_html__( 'All', 'et_core' ), 'off' => esc_html__( 'Any', 'et_core' ), ), 'default' => 'off', 'button_options' => array( 'button_type' => 'equal', ), 'description' => esc_html__( 'Choose whether any or all of the rules should be fulfilled', 'et_core' ), 'toggle_slug' => 'conditional_logic', 'show_if' => array( 'conditional_logic' => 'on', ), ), 'conditional_logic_rules' => array( 'label' => esc_html__( 'Rules', 'et_core' ), 'description' => esc_html__( 'Conditional logic rules can be used to hide and display different input fields conditionally based on how the visitor has interacted with different inputs.', 'et_core' ), 'type' => 'conditional_logic', 'option_category' => 'layout', 'depends_show_if' => 'on', 'toggle_slug' => 'conditional_logic', 'show_if' => array( 'conditional_logic' => 'on', ), ), ) ); } if ( 'bloom' === self::$owner ) { foreach ( $fields as $field_slug => &$field ) { if ( 'use_custom_fields' !== $field_slug ) { self::$_->array_set( $field, 'show_if.use_custom_fields', 'on' ); } } } return $fields; } protected static function _predefined_custom_field_select( $custom_fields, $provider, $account_name, $list_id = '' ) { $is_builder = 'builder' === self::$owner; $is_bloom = 'bloom' === self::$owner; $dependency = $is_builder ? 'parentModule:provider' : 'email_provider'; $show_if = array( $dependency => $provider, ); if ( $is_bloom ) { $show_if['account_name'] = $account_name; } if ( $list_id && $is_builder ) { $dependency = "parentModule:{$provider}_list"; $show_if[ $dependency ] = "{$account_name}|{$list_id}"; } else if ( $list_id && $is_bloom ) { $show_if['email_list'] = (string) $list_id; } $options = array( 'none' => esc_html__( 'Choose a field...', 'et_core' ) ); foreach ( $custom_fields as $field ) { $field_id = isset( $field['group_id'] ) ? $field['group_id'] : $field['field_id']; $options[ $field_id ] = $field['name']; } return array( 'label' => esc_html__( 'Field', 'et_core' ), 'type' => 'select', 'options' => $options, 'order' => array_keys( $options ), 'show_if' => $show_if, 'toggle_slug' => 'main_content', 'default' => 'none', 'description' => esc_html__( 'Choose a custom field. Custom fields must be defined in your email provider account.', 'et_core' ), ); } /** * Get field definitions * * @since 3.10 * * @param string $type Accepts 'custom_field' * @param string $for Accepts 'builder', 'bloom' * * @return array */ public static function get_definitions( $for, $type = 'custom_field' ) { self::$owner = $for; $fields = array(); if ( 'custom_field' === $type ) { $fields = self::_custom_field_definitions(); } return $fields; } public static function initialize() { self::$_ = ET_Core_Data_Utils::instance(); self::$_providers = ET_Core_API_Email_Providers::instance(); self::$_predefined_custom_field_support = array_keys( self::$_providers->names_by_slug( 'all', 'predefined_custom_fields' ) ); self::$_any_custom_field_type_support = self::$_providers->names_by_slug( 'all', 'any_custom_field_type' ); } } ET_Core_API_Email_Fields::initialize(); PKE\`Ą!components/api/email/iContact.phpnu[prepare_request( $this->FIELDS_URL ); $this->make_remote_request(); $result = array(); if ( $this->response->ERROR ) { et_debug( $this->get_error_message() ); return $result; } $data = $this->response->DATA['customfields']; foreach ( $data as &$custom_field ) { $custom_field = $this->transform_data_to_our_format( $custom_field, 'custom_field' ); } $fields = array(); foreach ( $data as $field ) { if ( 'text' !== $field['type'] ) { continue; } $field_id = $field['field_id']; $type = self::$_->array_get( $field, 'type', 'any' ); $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'any' ); $fields[ $field_id ] = $field; } return $fields; } protected function _set_custom_headers() { if ( ! empty( $this->custom_headers ) ) { return; } $this->custom_headers = array( 'Accept' => 'application/json', 'API-Version' => '2.2', 'API-AppId' => sanitize_text_field( $this->data['client_id'] ), 'API-Username' => sanitize_text_field( $this->data['username'] ), 'API-Password' => sanitize_text_field( $this->data['password'] ), ); } protected function _get_account_id() { if ( ! empty( $this->data['account_id'] ) ) { return $this->data['account_id']; } $this->prepare_request( 'https://app.icontact.com/icp/a' ); $this->make_remote_request(); if ( isset( $this->response->DATA['accounts'][0]['accountId'] ) ) { $this->data['account_id'] = $this->response->DATA['accounts'][0]['accountId']; } return $this->data['account_id']; } protected function _get_subscriber( $args, $exclude = null ) { $default_excludes = array( 'name', 'last_name' ); if ( is_array( $exclude ) ) { $exclude = array_merge( $default_excludes, $exclude ); } else if ( $exclude ) { $default_excludes[] = $exclude; $exclude = $default_excludes; } $args = $this->transform_data_to_provider_format( $args, 'subscriber', $exclude ); $url = add_query_arg( $args, $this->SUBSCRIBERS_URL ); $this->prepare_request( $url ); $this->make_remote_request(); if ( $this->response->ERROR || ! $this->response->DATA['contacts'] ) { return false; } return $this->response->DATA['contacts'][0]; } protected function _get_folder_id() { if ( ! empty( $this->data['folder_id'] ) ) { return $this->data['folder_id']; } $this->prepare_request( "{$this->BASE_URL}/{$this->data['account_id']}/c" ); $this->make_remote_request(); if ( isset( $this->response->DATA['clientfolders'][0]['clientFolderId'] ) ) { $this->data['folder_id'] = $this->response->DATA['clientfolders'][0]['clientFolderId']; } return $this->data['folder_id']; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, $field_id, $value ); } return $args; } protected function _set_urls() { $this->_set_custom_headers(); $account_id = $this->_get_account_id(); $folder_id = $this->_get_folder_id(); $this->BASE_URL = "{$this->BASE_URL}/{$account_id}/c/{$folder_id}"; $this->FIELDS_URL = "{$this->BASE_URL}/customfields"; $this->LISTS_URL = "{$this->BASE_URL}/lists"; $this->SUBSCRIBE_URL = "{$this->BASE_URL}/subscriptions"; $this->SUBSCRIBERS_URL = "{$this->BASE_URL}/contacts"; } /** * @inheritDoc */ public function get_account_fields() { return array( 'client_id' => array( 'label' => esc_html__( 'App ID', 'et_core' ), ), 'username' => array( 'label' => esc_html__( 'Username', 'et_core' ), ), 'password' => array( 'label' => esc_html__( 'App Password', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'listId', 'name' => 'name', 'subscribers_count' => 'total', ), 'subscriber' => array( 'name' => 'firstName', 'last_name' => 'lastName', 'email' => 'email', 'list_id' => 'listId', 'custom_fields' => 'custom_fields', ), 'subscriptions' => array( 'list_id' => 'listId', 'message_id' => 'confirmationMessageId', ), 'custom_field' => array( 'field_id' => 'privateName', 'name' => 'publicName', 'type' => 'fieldType', 'hidden' => '!displayToUser', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['client_id'] ) || empty( $this->data['username'] ) || empty( $this->data['password'] ) ) { return $this->API_KEY_REQUIRED; } $this->_set_urls(); $this->response_data_key = 'lists'; return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( empty( $this->data['client_id'] ) || empty( $this->data['username'] ) || empty( $this->data['password'] ) ) { return $this->API_KEY_REQUIRED; } $this->_set_urls(); if ( $this->_get_subscriber( $args ) ) { // Subscriber exists and is already subscribed to the list. return 'success'; } if ( ! $contact = $this->_get_subscriber( $args, 'list_id' ) ) { // Create new contact $body = $this->transform_data_to_provider_format( $args, 'subscriber' ); $body = $this->_process_custom_fields( $body ); $this->prepare_request( $this->SUBSCRIBERS_URL, 'POST', false, array( $body ), true ); $this->make_remote_request(); if ( $this->response->ERROR ) { return $this->get_error_message(); } $contact = $this->response->DATA['contacts'][0]; } // Subscribe contact to list $body = $this->transform_data_to_provider_format( $args, 'subscriptions' ); $body['contactId'] = $contact['contactId']; $body['status'] = isset( $args['message_id'] ) ? 'pending' : 'normal'; $this->prepare_request( $this->SUBSCRIBE_URL, 'POST', false, array( $body ), true ); return parent::subscribe( $args, $this->SUBSCRIBE_URL ); } } PKE\bLp p !components/api/email/MailPoet.phpnu[=' ); if ( $has_php53 && class_exists( '\MailPoet\API\API' ) ) { require_once( ET_CORE_PATH . 'components/api/email/_MailPoet3.php' ); $this->_init_provider_class( '3', $owner, $account_name, $api_key ); } else if ( class_exists( 'WYSIJA' ) ) { require_once( ET_CORE_PATH . 'components/api/email/_MailPoet2.php' ); $this->_init_provider_class( '2', $owner, $account_name, $api_key ); } } /** * Initiate provider class based on the version number. * * @param string $version Version number. * @param string $owner Owner. * @param string $account_name Account name. * @param string $api_key API key. */ protected function _init_provider_class( $version, $owner, $account_name, $api_key ) { if ( '3' === $version ) { $this->_MP = new ET_Core_API_Email_MailPoet3( $owner, $account_name, $api_key ); } else { $this->_MP = new ET_Core_API_Email_MailPoet2( $owner, $account_name, $api_key ); $this->custom_fields = false; } } /** * @inheritDoc */ public function get_account_fields() { return array(); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { if ( $this->_MP ) { return $this->_MP->get_data_keymap( $keymap ); } return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { $lists_data = $this->_MP ? $this->_MP->fetch_subscriber_lists() : self::$PLUGIN_REQUIRED; // Update data in Main MailPoet class, so correct lists data can be accessed if ( isset( $lists_data['success'] ) ) { $this->data = $lists_data['success']; $this->save_data(); return 'success'; } return $lists_data; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { return $this->_MP ? $this->_MP->subscribe( $args, $url ) : self::$PLUGIN_REQUIRED; } } PKE\l w#components/api/email/_MailPoet2.phpnu[ array( 'list_id' => 'id', 'name' => 'name', ), 'subscriber' => array( 'name' => 'first_name', 'last_name' => 'last_name', 'email' => 'email', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( ! class_exists( 'WYSIJA' ) ) { return self::$PLUGIN_REQUIRED; } $lists = array(); $list_model = WYSIJA::get( 'list', 'model' ); $all_lists_array = $list_model->get( array( 'name', 'list_id' ), array( 'is_enabled' => '1' ) ); foreach ( $all_lists_array as $list_details ) { $lists[ $list_details['list_id'] ]['name'] = sanitize_text_field( $list_details['name'] ); $user_model = WYSIJA::get( 'user_list', 'model' ); $all_subscribers_array = $user_model->get( array( 'user_id' ), array( 'list_id' => $list_details['list_id'] ) ); $subscribers_count = count( $all_subscribers_array ); $lists[ $list_details['list_id'] ]['subscribers_count'] = sanitize_text_field( $subscribers_count ); } $this->data['is_authorized'] = true; if ( ! empty( $lists ) ) { $this->data['lists'] = $lists; } $this->save_data(); return array( 'success' => $this->data ); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( ! class_exists( 'WYSIJA' ) ) { ET_Core_Logger::error( self::$PLUGIN_REQUIRED ); return esc_html__( 'An error occurred. Please try again later.', 'et_core' ); } global $wpdb; $wpdb->wysija_user_table = $wpdb->prefix . 'wysija_user'; $wpdb->wysija_user_lists_table = $wpdb->prefix . 'wysija_user_list'; // get the ID of subscriber if they're in the list already $subscriber_id = $wpdb->get_var( $wpdb->prepare( "SELECT user_id FROM {$wpdb->wysija_user_table} WHERE email = %s", array( et_core_sanitized_previously( $args['email'] ), ) ) ); $already_subscribed = 0; // if current email is subscribed, then check whether it subscribed to the current list if ( ! empty( $subscriber_id ) ) { $already_subscribed = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->wysija_user_lists_table} WHERE user_id = %s AND list_id = %s", array( $subscriber_id, et_core_sanitized_previously( $args['list_id'] ), ) ) ); } unset( $wpdb->wysija_user_table ); unset( $wpdb->wysija_user_list_table ); // if email is not subscribed to current list, then subscribe. if ( 0 === $already_subscribed ) { $new_user = array( 'user' => array( 'email' => et_core_sanitized_previously( $args['email'] ), 'firstname' => et_core_sanitized_previously( $args['name'] ), 'lastname' => et_core_sanitized_previously( $args['last_name'] ), ), 'user_list' => array( 'list_ids' => array( et_core_sanitized_previously( $args['list_id'] ) ), ), ); $mailpoet_class = WYSIJA::get( 'user', 'helper' ); $error_message = $mailpoet_class->addSubscriber( $new_user ); $error_message = is_int( $error_message ) ? 'success' : $error_message; } else { $error_message = esc_html__( 'Already Subscribed', 'bloom' ); } return $error_message; } } PKE\p E=&=&"components/api/email/FluentCRM.phpnu[ array( 'list_id' => 'id', 'name' => 'title', ), 'subscriber' => array( 'email' => 'email', 'last_name' => 'last_name', 'name' => 'first_name', 'custom_fields' => 'custom_fields', ), 'custom_field' => array( 'field_id' => 'slug', 'name' => 'label', 'type' => 'type', 'hidden' => 'hidden', 'options' => 'options', ), 'custom_field_option' => array( 'id' => 'value', 'name' => 'value', ), 'custom_field_type' => array( // Us <=> Them. 'radio' => 'radio', 'checkbox' => 'checkbox', // Us => Them. 'input' => 'text', 'select' => 'select-one', // Them => Us. 'text' => 'input', 'number' => 'input', 'date' => 'input', 'date_time' => 'input', 'select-one' => 'select', 'select-multi' => 'checkbox', ), ); return parent::get_data_keymap( $keymap ); } /** * {@inheritdoc} * * FluentCRM is self hosted and all the fields can be managed on the plugin itself. */ protected function _fetch_custom_fields( $list_id = '', $list = array() ) { static $processed = null; if ( is_null( $processed ) ) { // A. Default custom fields. $processed = array( 'address_line_1' => array( 'field_id' => 'address_line_1', 'name' => __( 'Address Line 1', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'address_line_2' => array( 'field_id' => 'address_line_2', 'name' => __( 'Address Line 2', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'postal_code' => array( 'field_id' => 'postal_code', 'name' => __( 'Postal Code', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'city' => array( 'field_id' => 'city', 'name' => __( 'City', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'state' => array( 'field_id' => 'state', 'name' => __( 'State', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'country' => array( 'field_id' => 'country', 'name' => __( 'Country', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'phone' => array( 'field_id' => 'phone', 'name' => __( 'Phone', 'et_builder' ), 'type' => 'input', 'hidden' => false, ), 'status' => array( 'field_id' => 'status', 'name' => __( 'Enable Double Optin', 'et_builder' ), 'type' => 'input', 'required_mark' => 'off', 'default' => 'pending', 'hidden' => true, ), ); // B. Contact custom fields. $contact_custom_fields = fluentcrm_get_option( 'contact_custom_fields', array() ); if ( ! empty( $contact_custom_fields ) ) { foreach ( $contact_custom_fields as $field ) { // 1. Transform field data to fit our format. $field = $this->transform_data_to_our_format( $field, 'custom_field' ); $field_id = $field['field_id']; $type = $field['type']; // 2. Transform field type to fit our supported field type. $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'any' ); if ( 'select-multi' === $type ) { $field['type_origin'] = $type; } // 3. Transform `options` data to fit our format (`id` => `name`). if ( ! empty( $field['options'] ) ) { $options = array(); foreach ( $field['options'] as $option ) { $option = array( 'value' => $option ); $option = $this->transform_data_to_our_format( $option, 'custom_field_option' ); $options[ $option['id'] ] = $option['name']; } $field['options'] = $options; } $processed[ $field_id ] = $field; } } } return $processed; } /** * {@inheritdoc} * * FluentCRM is self hosted and all the fields can be managed on the plugin itself. */ public function get_account_fields() { return array(); } /** * {@inheritdoc} * * FluentCRM is self hosted and all the lists can be managed on the plugin itself. */ public function fetch_subscriber_lists() { if ( ! defined( 'FLUENTCRM' ) ) { return self::$PLUGIN_REQUIRED; // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. } $list_tags = array(); // Lists. $lists = FluentCrmApi( 'lists' )->all(); foreach ( $lists as $list ) { $list_tags[ 'list_' . $list->id ] = array( 'list_id' => 'list_' . $list->id, 'name' => 'List: ' . $list->title, 'subscribers_count' => 0, ); } // Tags. $tags = FluentCrmApi( 'tags' )->all(); foreach ( $tags as $tag ) { $list_tags[ 'tags_' . $tag->id ] = array( 'list_id' => 'tags_' . $tag->id, 'name' => 'Tag: ' . $tag->title, 'subscribers_count' => 0, ); } // Combine both of lists and tags because there is no other way to display both // with different fields. $this->data['lists'] = $list_tags; $this->data['custom_fields'] = $this->_fetch_custom_fields( '', array() ); $this->data['is_authorized'] = true; $this->save_data(); return 'success'; } /** * {@inheritdoc} */ protected function _process_custom_fields( $args ) { if ( ! empty( $args['custom_fields'] ) ) { $custom_fields = $args['custom_fields']; foreach ( $custom_fields as $field_id => $field_value ) { if ( $field_value ) { $field_type = self::$_->array_get( $this->data['custom_fields'][ $field_id ], 'type' ); $field_type_origin = self::$_->array_get( $this->data['custom_fields'][ $field_id ], 'type_origin' ); // Transform `checkbox` value into string separated by comma i.e. 'val1,val2'. // However, if the field type origin is `select-multi`, we have to use array // values instead. if ( 'checkbox' === $field_type ) { $field_value = 'select-multi' === $field_type_origin ? array_values( $field_value ) : implode( ',', $field_value ); } $args[ $field_id ] = $field_value; } } if ( isset( $custom_fields['status'] ) ) { $args['status'] = 'pending'; } unset( $args['custom_fields'] ); } return $args; } /** * {@inheritdoc} */ public function subscribe( $args, $url = '' ) { if ( ! defined( 'FLUENTCRM' ) ) { ET_Core_Logger::error( self::$PLUGIN_REQUIRED ); // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. return esc_html__( 'An error occurred. Please try again later.', 'et_core' ); } $contact = $this->transform_data_to_provider_format( $args, 'subscriber' ); $contact = $this->_process_custom_fields( $contact ); // IP Address. $ip_address = 'true' === self::$_->array_get( $args, 'ip_address', 'true' ) ? et_core_get_ip_address() : ''; $contact['ip_address'] = $ip_address; // Name. if ( empty( $contact['last_name'] ) ) { $contact['full_name'] = $contact['first_name']; unset( $contact['first_name'] ); unset( $contact['last_name'] ); } // List or Tag. $list_or_tag_id = $args['list_id']; if ( false === strpos( $list_or_tag_id, 'tags_' ) ) { $contact['lists'] = array( intval( str_replace( 'list_', '', $list_or_tag_id ) ) ); } else { $contact['tags'] = array( intval( str_replace( 'tags_', '', $list_or_tag_id ) ) ); } $contact = array_filter( $contact ); // Email. if ( empty( $contact['email'] ) || ! is_email( $contact['email'] ) ) { return esc_html__( 'Email Validation has been failed.', 'et_core' ); } FluentCrmApi( 'contacts' )->createOrUpdate( $contact ); return 'success'; } } PKE\'xcomponents/api/email/Emma.phpnu[ 'api_key', 'password' => 'private_api_key', ); /** * @inheritDoc */ public $name = 'Emma'; /** * @inheritDoc */ public $slug = 'emma'; protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $this->response_data_key = false; $this->prepare_request( $this->_get_custom_fields_url() ); return parent::_fetch_custom_fields( $list_id, $list ); } protected function _get_custom_fields_url() { return "https://api.e2ma.net/{$this->data['user_id']}/fields?group_types=all"; } protected function _get_lists_url() { return "https://api.e2ma.net/{$this->data['user_id']}/groups?group_types=all"; } protected function _get_subscribe_url() { return "https://api.e2ma.net/{$this->data['user_id']}/members/signup"; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); } self::$_->array_set( $args, "fields.{$field_id}", $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'Public API Key', 'et_core' ), ), 'private_api_key' => array( 'label' => esc_html__( 'Private API Key', 'et_core' ), ), 'user_id' => array( 'label' => esc_html__( 'Account ID', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'name' => 'group_name', 'list_id' => 'member_group_id', 'subscribers_count' => 'active_count', ), 'subscriber' => array( 'email' => 'email', 'name' => 'fields.first_name', 'last_name' => 'fields.last_name', 'list_id' => '@group_ids', 'custom_fields' => 'custom_fields', ), 'custom_field' => array( 'field_id' => 'shortcut_name', 'name' => 'display_name', 'options' => 'options', 'type' => 'widget_type', ), 'custom_field_type' => array( // Us <=> Them 'radio' => 'radio', // Us => Them 'select' => 'select one', 'text' => 'long', 'checkbox' => 'check_multiple', // Them => Us 'text' => 'input', 'long' => 'text', 'check_multiple' => 'checkbox', 'select one' => 'select', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $this->LISTS_URL = $this->_get_lists_url(); $this->response_data_key = false; return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $url = $this->_get_subscribe_url(); $this->response_data_key = 'member_id'; $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); $args = $this->_process_custom_fields( $args ); $this->prepare_request( $url, 'POST', false, $args, true ); return parent::subscribe( $args, $url ); } } PKE\x,"components/api/email/Ontraport.phpnu[_maybe_set_custom_headers(); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { static $fields = null; if ( is_null( $fields ) ) { $this->response_data_key = null; parent::_fetch_custom_fields( $list_id, $list ); if ( $this->response->ERROR ) { et_debug( $this->get_error_message() ); return array(); } $fields = array(); $fields_unprocessed = self::$_->array_get( $this->response->DATA, 'data.[0].fields', $fields ); foreach ( $fields_unprocessed as $field_id => $field ) { if ( in_array( $field_id, array( 'firstname', 'lastname', 'email' ) ) ) { continue; } $type = $field['type']; $field['field_id'] = $field_id; $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'text' ); $fields[ $field_id ] = $this->transform_data_to_our_format( $field, 'custom_field' ); } } return $fields; } protected function _get_subscriber_list_type( $list_id ) { $sequence_key = 'seq:' . $list_id; $campaign_key = 'camp:' . $list_id; if ( isset( $this->data['lists'][ $campaign_key ] ) ) { return 'Campaign'; } if ( isset( $this->data['lists'][ $sequence_key ] ) ) { return 'Sequence'; } return 'Campaign'; } protected function _maybe_set_custom_headers() { if ( empty( $this->custom_headers ) && isset( $this->data['api_key'] ) && isset( $this->data['client_id'] ) ) { $this->custom_headers = array( 'Api-Appid' => sanitize_text_field( $this->data['client_id'] ), 'Api-Key' => sanitize_text_field( $this->data['api_key'] ), ); } } protected function _prefix_subscriber_lists( $name_prefix, $id_prefix ) { $lists = array(); foreach ( $this->data['lists'] as $list_id => $list ) { $key = $id_prefix . $list_id; if ( ! $list['name'] ) { $list['name'] = $list_id; } $lists[ $key ] = $list; $lists[ $key ]['name'] = $name_prefix . $list['name']; $lists[ $key ]['list_id'] = $key; } $this->data['lists'] = $lists; $this->save_data(); } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_keys( $value ); if ( 'checkbox' === $this->data['custom_fields'][ $field_id ]['type'] ) { // Determine if checkbox is a single checkbox or a list. // In case of single checkbox pass `1` as a value if ( ! empty( $this->data['custom_fields'][ $field_id ]['options'] ) ) { $value = implode( '*/*', $value ); $value = "*/*{$value}*/*"; } else { $value = '1'; } } else { $value = array_pop( $value ); } } self::$_->array_set( $args, $field_id, $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), 'client_id' => array( 'label' => esc_html__( 'APP ID', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'name' => 'name', 'list_id' => 'drip_id', 'subscribers_count' => 'subscriber_count', ), 'subscriber' => array( 'name' => 'firstname', 'last_name' => 'lastname', 'email' => 'email', 'custom_fields' => 'custom_fields', ), 'custom_field' => array( 'field_id' => 'field_id', 'type' => 'type', 'name' => 'alias', 'options' => 'options', ), 'custom_field_type' => array( // Us => Them 'input' => 'text', 'textarea' => 'textlong', 'checkbox' => 'list', 'select' => 'drop', // Them => Us 'text' => 'input', 'textlong' => 'textarea', 'list' => 'checkbox', 'check' => 'checkbox', 'drop' => 'select', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) || empty( $this->data['client_id'] ) ) { return $this->API_KEY_REQUIRED; } $this->_maybe_set_custom_headers(); $this->response_data_key = 'data'; parent::fetch_subscriber_lists(); $this->_prefix_subscriber_lists( 'Sequence: ', 'seq:' ); $sequences = $this->data['lists']; $url = 'https://api.ontraport.com/1/CampaignBuilderItems'; $url = add_query_arg( 'listFields', 'id,name,subs', $url ); $this->data_keys['list']['list_id'] = 'id'; $this->data_keys['list']['subscribers_count'] = 'subs'; $this->prepare_request( $url ); $this->response_data_key = 'data'; $result = parent::fetch_subscriber_lists(); $this->_prefix_subscriber_lists( 'Campaign: ', 'camp:' ); $this->data['lists'] = array_merge( $this->data['lists'], $sequences ); $this->save_data(); return $result; } public function get_subscriber( $email ) { $args = array( 'objectID' => '0', 'email' => rawurlencode( $email ), ); $url = add_query_arg( $args, $this->SUBSCRIBE_URL . '/object/getByEmail' ); $this->prepare_request( $url ); $this->make_remote_request(); return self::$_->array_get( $this->response->DATA, 'data.id', false ); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( empty( $this->data['api_key'] ) || empty( $this->data['client_id'] ) ) { return $this->API_KEY_REQUIRED; } $list_id = $args['list_id']; $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); $args = $this->_process_custom_fields( $args ); $args['objectID'] = 0; $url = $this->SUBSCRIBE_URL . '/Contacts/saveorupdate'; // Create or update contact $this->prepare_request( $url, 'POST', false, $args ); $this->make_remote_request(); if ( $this->response->ERROR ) { return $this->get_error_message(); } $list_id_parts = explode( ':', $list_id ); $list_id = array_pop( $list_id_parts ); $data = $this->response->DATA['data']; // Subscribe contact to list $url = $this->SUBSCRIBE_URL . '/objects/subscribe'; $args = array( 'ids' => self::$_->array_get( $data, 'id', $data['attrs']['id'] ), 'add_list' => $list_id, 'sub_type' => $this->_get_subscriber_list_type( $list_id ), 'objectID' => 0, ); $this->prepare_request( $url, 'PUT', false, $args ); return parent::subscribe( $args, $url ); } } PKE\RMM"components/api/email/Feedblitz.phpnu[ $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, $field_id, rawurlencode( $value ) ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'subscribersummary.subscribers', ), 'subscriber' => array( 'list_id' => 'listid', 'email' => 'email', 'name' => 'FirstName', 'last_name' => 'LastName', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'rsp.err.@attributes.msg', ) ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $this->http->expects_json = false; $this->response_data_key = false; $this->LISTS_URL = add_query_arg( 'key', $this->data['api_key'], $this->LISTS_URL ); parent::fetch_subscriber_lists(); $response = $this->data_utils->process_xmlrpc_response( $this->response->DATA, true ); $response = $this->data_utils->xml_to_array( $response ); if ( $this->response->ERROR || ! empty( $response['rsp']['err']['@attributes']['msg'] ) ) { return $this->get_error_message(); } $this->data['lists'] = $this->_process_subscriber_lists( $response['syndications']['syndication'] ); $this->data['is_authorized'] = true; $this->save_data(); return 'success'; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $query_args = array( 'email' => rawurlencode( $args['email'] ), 'name' => empty( $args['name'] ) ? '' : rawurlencode( $args['name'] ), 'last_name' => empty( $args['last_name'] ) ? '' : rawurlencode( $args['last_name'] ), 'custom_fields' => $args['custom_fields'], 'list_id' => $args['list_id'], ); $query = $this->transform_data_to_provider_format( $query_args, 'subscriber' ); $query = $this->_process_custom_fields( $query ); $query['key'] = rawurlencode( $this->data['api_key'] ); $url = add_query_arg( $query, "{$this->SUBSCRIBE_URL}?SimpleApiSubscribe" ); $this->prepare_request( $url, 'GET', false, null, false, false ); $this->make_remote_request(); $response = $this->data_utils->process_xmlrpc_response( $this->response->DATA, true ); $response = $this->data_utils->xml_to_array( $response ); if ( $this->response->ERROR || ! empty( $response['rsp']['err']['@attributes']['msg'] ) ) { return $this->get_error_message(); } if ( ! empty( $response['rsp']['success']['@attributes']['msg'] ) ) { return $response['rsp']['success']['@attributes']['msg']; } return 'success'; } } PKE\:uu#components/api/email/_MailPoet3.phpnu[getSubscriberFields(); $processed = array(); foreach ( $fields as $field ) { $field_id = $field['id']; $field_name = $field['name']; if ( in_array( $field_id, array( 'email', 'first_name', 'last_name' ) ) ) { continue; } $processed[ $field_id ] = array( 'field_id' => $field_id, 'name' => $field_name, 'type' => 'any', ); } } return $processed; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $custom_fields = $args['custom_fields']; $required_fields = $this->_get_required_custom_fields(); // Filter missing required custom field. $missing_fields = array_diff( $required_fields, array_keys( $custom_fields ) ); // Fill-up missing required custom fields with dummy content and merge with available ones. // This is required because of how MailPoet API validates the custom fields currently // and there's no filters available to alter this behavior right now. $fields = array_merge( $custom_fields, array_fill_keys( $missing_fields, 'n/a' ) ); unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_keys( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, $field_id, $value ); } return $args; } /** * Get required custom fields. * * @return $required_fields */ protected function _get_required_custom_fields() { $fields = \MailPoet\API\API::MP( 'v1' )->getSubscriberFields(); $required_fields = []; foreach ( $fields as $field ) { // Custom field ids have `cf_` prefix. Also we need only the required ones. if ( false !== strpos( $field['id'], 'cf_' ) && $field['params']['required'] ) { $required_fields[] = $field['id']; } } return $required_fields; } /** * @inheritDoc */ public function get_account_fields() { return array(); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', ), 'subscriber' => array( 'name' => 'first_name', 'last_name' => 'last_name', 'email' => 'email', 'custom_fields' => 'custom_fields', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( ! class_exists( '\MailPoet\API\API' ) ) { return self::$PLUGIN_REQUIRED; } $data = \MailPoet\API\API::MP( 'v1' )->getLists(); if ( ! empty( $data ) ) { $this->data['lists'] = $this->_process_subscriber_lists( $data ); $list = is_array( $data ) ? array_shift( $data ) : array(); $this->data['custom_fields'] = $this->_fetch_custom_fields( '', $list ); } $this->data['is_authorized'] = true; $this->save_data(); return array( 'success' => $this->data ); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( ! class_exists( '\MailPoet\API\API' ) ) { ET_Core_Logger::error( self::$PLUGIN_REQUIRED ); return esc_html__( 'An error occurred. Please try again later.', 'et_core' ); } $subscriber = array(); $args = et_core_sanitized_previously( $args ); $subscriber_data = $this->transform_data_to_provider_format( $args, 'subscriber' ); $subscriber_data = $this->_process_custom_fields( $subscriber_data ); $subscriber_data = self::$_->array_flatten( $subscriber_data ); $result = 'success'; $lists = array( $args['list_id'] ); unset( $subscriber_data['custom_fields'] ); /** * Check if the subscriber with this email already exists. */ try { $subscriber = \MailPoet\API\API::MP( 'v1' )->getSubscriber( $subscriber_data['email'] ); } catch ( \Exception $e ) { $subscriber = array(); } /** * If subscriber is not found, add as a new subscriber. Otherwise, add existing subscriber to the lists. */ if ( empty( $subscriber ) ) { try { \MailPoet\API\API::MP( 'v1' )->addSubscriber( $subscriber_data, $lists ); } catch ( Exception $exception ) { $result = $exception->getMessage(); } } else { try { \MailPoet\API\API::MP( 'v1' )->subscribeToLists( $subscriber['id'], $lists ); } catch ( Exception $exception ) { $result = $exception->getMessage(); } } return $result; } } PKE\g& & #components/api/email/MailerLite.phpnu[_maybe_set_custom_headers(); } protected function _maybe_set_custom_headers() { if ( empty( $this->custom_headers ) && isset( $this->data['api_key'] ) ) { $this->custom_headers = array( 'X-MailerLite-ApiKey' => "{$this->data['api_key']}" ); } } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, "fields.{$field_id}", $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'active', ), 'subscriber' => array( 'name' => 'fields.name', 'last_name' => 'fields.last_name', 'email' => 'email', 'custom_fields' => 'custom_fields', 'resubscribe' => 'resubscribe', ), 'error' => array( 'error_message' => 'error.message', ), 'custom_field' => array( 'field_id' => 'key', 'name' => 'title', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $this->_maybe_set_custom_headers(); $this->response_data_key = false; return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $args['resubscribe'] = 1; $url = "{$this->LISTS_URL}/{$args['list_id']}/subscribers"; return parent::subscribe( $args, $url ); } } PKE\3|UD&D& components/api/email/HubSpot.phpnu[_maybe_set_custom_headers(); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $this->response_data_key = false; $fields_unprocessed = parent::_fetch_custom_fields( $list_id, $list ); $fields = array(); foreach ( $fields_unprocessed as $field ) { $field_id = $field['field_id']; if ( ! isset( $field['options'] ) ) { $fields[ $field_id ] = $field; continue; } $options = array(); foreach ( $field['options'] as $option ) { $option = $this->transform_data_to_our_format( $option, 'custom_field_option' ); $id = $option['id']; $options[ $id ] = $option['name']; } $field['options'] = $options; $fields[ $field_id ] = $field; } return $fields; } /** * Whether current request needs API Key instead. * * It's needed to check existing API Key implementation when no Access Token presents. * * @since 4.18.1 * * @return boolean API Key status. */ protected function _is_api_key_needed() { // Bail early if Access Token exists. if ( ! empty( $this->data['token'] ) ) { return false; } // Otherwise check API Key. return ! empty( $this->data['api_key'] ); } /** * Get list add contact URL. * * @since 3.0.72 * @since 4.18.1 Replaces hapikey query string with authentication on headers. * * @param string $list_id List ID. * * @return string URL for adding contact to list. */ protected function _get_list_add_contact_url( $list_id ) { $url = "{$this->BASE_URL}/lists/{$list_id}/add"; if ( $this->_is_api_key_needed() ) { $url = add_query_arg( 'hapikey', $this->data['api_key'], $url ); } return $url; } /** * Maybe need to set custom headers. * * @since 4.18.1 */ protected function _maybe_set_custom_headers() { if ( ! empty( $this->custom_headers ) ) { return; } if ( ! empty( $this->data['token'] ) ) { $this->custom_headers = array( 'authorization' => 'Bearer ' . sanitize_text_field( $this->data['token'] ), ); } } /** * Maybe set URLs. * * @since 3.0.72 * @since 4.18.1 Replaces hapikey query string with access token headers. * * @param string $email Contact email. */ protected function _maybe_set_urls( $email = '' ) { // Only use `hapikey` when Access Token doesn't exist and the API Key not empty. if ( $this->_is_api_key_needed() ) { $this->FIELDS_URL = add_query_arg( 'hapikey', $this->data['api_key'], $this->FIELDS_URL ); // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. $this->LISTS_URL = add_query_arg( 'hapikey', $this->data['api_key'], $this->LISTS_URL ); // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. $this->SUBSCRIBE_URL = add_query_arg( 'hapikey', $this->data['api_key'], $this->SUBSCRIBE_URL ); // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. } if ( $email ) { $this->SUBSCRIBE_URL = str_replace( '@email@', rawurlencode( $email ), $this->SUBSCRIBE_URL ); } } protected function _process_custom_fields( $args ) { $args['properties'] = array(); if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; $properties = array(); unset( $args['custom_fields'] ); $field_types = array( 'radio', 'booleancheckbox', ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); $value = implode( ';', $value ); } elseif ( in_array( $this->data['custom_fields'][ $field_id ]['type'], $field_types, true ) ) { // Should use array key. Sometimes it's different than value and Hubspot expects the key $radio_options = $this->data['custom_fields'][ $field_id ]['options']; $value = array_search( $value, $radio_options ); } $properties[] = array( 'property' => $field_id, 'value' => $value, ); } $args['properties'] = $properties; return $args; } /** * @inheritDoc * * @since 4.18.1 Replaces api_key field with token. */ public function get_account_fields() { return array( 'token' => array( 'label' => esc_html__( 'Access Token', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'listId', 'name' => 'name', 'subscribers_count' => 'metaData.size', ), 'subscriber' => array( 'email' => 'email', 'name' => 'firstname', 'last_name' => 'lastname', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'message', ), 'custom_field' => array( 'field_id' => 'name', 'name' => 'label', 'type' => 'fieldType', 'options' => 'options', 'hidden' => 'hidden', ), 'custom_field_option' => array( 'id' => 'value', 'name' => 'label', ), 'custom_field_type' => array( // Us <=> Them 'select' => 'select', 'radio' => 'radio', 'checkbox' => 'checkbox', // Us => Them 'input' => 'text', 'textarea' => 'text', // Them => Us 'text' => 'input', 'booleancheckbox' => 'booleancheckbox', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc * * @since 4.18.1 Replaces API Key usage with Access Token. */ public function fetch_subscriber_lists() { if ( empty( $this->data['token'] ) && empty( $this->data['api_key'] ) ) { return self::$TOKEN_REQUIRED; // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. } $this->_maybe_set_custom_headers(); $this->_maybe_set_urls(); /** * The maximum number of subscriber lists to request from Hubspot's API at a time. * * @since 3.0.75 * * @param int $max_lists Value must be <= 250. */ $max_lists = (int) apply_filters( 'et_core_api_email_hubspot_max_lists', 250 ); $this->LISTS_URL = add_query_arg( 'count', $max_lists, $this->LISTS_URL ); $this->response_data_key = 'lists'; return parent::fetch_subscriber_lists(); } /** * @inheritDoc * * @since 4.18.1 Replaces API Key usage with Access Token. */ public function subscribe( $args, $url = '' ) { if ( empty( $this->data['token'] ) && empty( $this->data['api_key'] ) ) { return self::$TOKEN_REQUIRED; // phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Widely used on all email provider classes. } $this->_maybe_set_custom_headers(); $this->_maybe_set_urls( $args['email'] ); $args = $this->_process_custom_fields( $args ); $data = array( 'properties' => array( array( 'property' => 'email', 'value' => et_core_sanitized_previously( $args['email'] ), ), array( 'property' => 'firstname', 'value' => et_core_sanitized_previously( $args['name'] ), ), array( 'property' => 'lastname', 'value' => et_core_sanitized_previously( $args['last_name'] ), ), ), ); $data['properties'] = array_merge( $data['properties'], $args['properties'] ); $this->prepare_request( $this->SUBSCRIBE_URL, 'POST', false, $data, true ); $this->make_remote_request(); if ( $this->response->ERROR ) { return $this->get_error_message(); } $url = $this->_get_list_add_contact_url( $args['list_id'] ); $data = array( 'emails' => array( $args['email'] ), ); $this->prepare_request( $url, 'POST', false, $data, true ); $this->make_remote_request(); if ( $this->response->ERROR ) { return $this->get_error_message(); } return 'success'; } } PKE\T #components/api/email/SendinBlue.phpnu[_maybe_set_custom_headers(); } protected function _maybe_set_custom_headers() { if ( empty( $this->custom_headers ) && isset( $this->data['api_key'] ) ) { $this->custom_headers = array( 'api-key' => $this->data['api_key'] ); } } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; $fileds_info = $args['fileds_info']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( ! isset( $fileds_info[ $field_id ] ) ) { continue; } if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $type = self::$_->array_get( $fileds_info, "{$field_id}.native_type" ); // User checked the checkbox, when native type is Boolean. $value = 'boolean' === $type ? true : array_pop( $value ); } } self::$_->array_set( $args, "attributes.{$field_id}", $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => $this->_should_use_legacy_api() ? 'total_subscribers' : 'totalSubscribers', ), 'subscriber' => array( 'email' => 'email', 'name' => 'attributes.FIRSTNAME', 'last_name' => 'attributes.LASTNAME', 'list_id' => $this->_should_use_legacy_api() ? '@listid' : '@listIds', 'custom_fields' => 'custom_fields', 'updateEnabled' => 'updateEnabled', ), 'custom_field' => array( 'native_type' => 'type', 'field_id' => 'name', 'name' => 'name', ), ); return parent::get_data_keymap( $keymap ); } public function get_subscriber( $email ) { $this->prepare_request( "{$this->USERS_URL}/{$email}", 'GET' ); $this->make_remote_request(); if ( $this->response->ERROR || ! isset( $this->response->DATA['listid'] ) ) { return false; } if ( isset( $this->response->DATA['code'] ) && 'success' !== $this->response->DATA['code'] ) { return false; } return $this->response->DATA; } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } if ( empty( $this->custom_headers ) ) { $this->_maybe_set_custom_headers(); } $use_legacy_api = $this->_should_use_legacy_api(); if ( $use_legacy_api ) { $this->LISTS_URL = 'https://api.sendinblue.com/v2.0/list'; // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Keep the variable name. $this->response_data_key = 'data'; $params = array( 'page' => 1, 'page_limit' => 2, ); } else { $this->response_data_key = 'lists'; $params = array(); } /** * The maximum number of subscriber lists to request from Sendinblue's API. * * @since 4.11.4 * * @param int $max_lists */ $max_lists = (int) apply_filters( 'et_core_api_email_sendinblue_max_lists', 50 ); $url = "{$this->LISTS_URL}?limit={$max_lists}&offset=0&sort=desc"; $this->prepare_request( $url, 'GET', false, $params ); $this->request->data_format = 'body'; parent::fetch_subscriber_lists(); if ( $this->response->ERROR ) { return $this->response->ERROR_MESSAGE; } if ( isset( $this->response->DATA['code'] ) && 'success' !== $this->response->DATA['code'] ) { return $this->response->DATA['message']; } $result = 'success'; $this->data['is_authorized'] = 'true'; $list_data = $use_legacy_api ? $this->response->DATA['data']['lists'] : ( isset( $this->response->DATA['lists'] ) ? $this->response->DATA['lists'] : [] ); if ( ! empty( $list_data ) ) { $this->data['lists'] = $this->_process_subscriber_lists( $list_data ); $this->save_data(); } return $result; } /** * Get custom fields for a subscriber list. * Need to override the method in the child class to dynamically use the API endpoint * and response_data_key based on the API version being used. * * @param int|string $list_id The list ID. * @param array $list The lists array. * * @return array */ protected function _fetch_custom_fields( $list_id = '', $list = array() ) { if ( $this->_should_use_legacy_api() ) { $this->FIELDS_URL = 'https://api.sendinblue.com/v2.0/attribute/normal'; // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Keep the variable name. $this->response_data_key = 'data'; } else { $this->response_data_key = 'attributes'; } return parent::_fetch_custom_fields( $list_id, $list ); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $args['list_id'] = array( absint( $args['list_id'] ) ); // in V3 the list id has to be integer. if ( $this->_should_use_legacy_api() ) { $this->SUBSCRIBE_URL = 'https://api.sendinblue.com/v2.0/user/createdituser'; // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Keep the variable name. $existing_user = $this->get_subscriber( $args['email'] ); if ( false !== $existing_user ) { $args['list_id'] = array_unique( array_merge( $args['list_id'], $existing_user['listid'] ) ); } } else { $args['updateEnabled'] = true; // Update existing contact if exists. // Process data and encode to json, the new API (v3) uses json encoded body params. if ( ! in_array( 'ip_address', $args, true ) || 'true' === $args['ip_address'] ) { $args['ip_address'] = et_core_get_ip_address(); } elseif ( 'false' === $args['ip_address'] ) { $args['ip_address'] = '0.0.0.0'; } $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); if ( $this->custom_fields ) { $args['fileds_info'] = $this->_fetch_custom_fields(); $args = $this->_process_custom_fields( $args ); } $this->prepare_request( $this->SUBSCRIBE_URL, 'POST', false, $args, true ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Keep the variable name. } return parent::subscribe( $args, $this->SUBSCRIBE_URL ); } /** * Check if the api-key being used is legacy (v2). * * @return boolean */ protected function _should_use_legacy_api() { $api_key = isset( $this->data['api_key'] ) ? $this->data['api_key'] : ''; return ! empty( $api_key ) && 'xkeysib-' !== substr( $api_key, 0, 8 ); } } PKE\IwNP++!components/api/email/Mailster.phpnu[owner ); if ( 'bloom' === $this->owner && isset( $args['optin_id'] ) ) { $optin_form = ET_Bloom::get_this()->dashboard_options[ $args['optin_id'] ]; $optin_name = $optin_form['optin_name']; } return sprintf( '%1$s %2$s "%3$s" on %4$s', esc_html( $owner ), esc_html__( 'Opt-in', 'et_core' ), esc_html( $optin_name ), wp_get_referer() ); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { static $fields = null; if ( is_null( $fields ) ) { $customfields = mailster()->get_custom_fields(); if ( empty( $customfields ) ) { return $fields; } $field_types = self::$_->array_get( $this->data_keys, 'custom_field_type' ); foreach ( $customfields as $field_id => $field ) { $field = $this->transform_data_to_our_format( $field, 'custom_field' ); $type = self::$_->array_get( $field, 'type', 'any' ); $field['field_id'] = $field_id; if ( $field_types && ! isset( $field_types[ $type ] ) ) { // Unsupported field type. Make it 'text' instead. $type = 'textfield'; } $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'input' ); $fields[ $field_id ] = $field; } } return $fields; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); $registered_custom_fields = self::$_->array_get( $this->data, 'custom_fields', array() ); foreach ( $fields as $field_id => $value ) { $field_type = isset( $registered_custom_fields[ $field_id ] ) && isset( $registered_custom_fields[ $field_id ]['type'] ) ? $registered_custom_fields[ $field_id ]['type'] : false; // Mailster doesn't support multiple checkboxes and if it appears here that means the checkbox is checked if ( 'checkbox' === $field_type ) { $value = 1; } if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, $field_id, $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array(); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'ID', 'name' => 'name', 'subscribers_count' => 'subscribers', ), 'subscriber' => array( 'dbl_optin' => 'status', 'email' => 'email', 'last_name' => 'lastname', 'name' => 'firstname', 'custom_fields' => 'custom_fields', ), 'custom_field' => array( 'name' => 'name', 'type' => 'type', 'options' => 'values', 'hidden' => 'hidden', ), 'custom_field_type' => array( // Us => Them 'textarea' => 'textarea', 'radio' => 'radio', 'checkbox' => 'checkbox', 'input' => 'textfield', 'select' => 'dropdown', // Them => Us 'textfield' => 'input', 'dropdown' => 'select', ), ); return parent::get_data_keymap( $keymap ); } public function fetch_subscriber_lists() { if ( ! function_exists( 'mailster' ) ) { return esc_html__( 'Mailster Newsletter Plugin is not enabled!', 'et_core' ); } $lists = mailster( 'lists' )->get( null, null, true ); $error_message = esc_html__( 'No lists were found. Please create a Mailster list first!', 'et_core' ); if ( $lists ) { $error_message = 'success'; $this->data['lists'] = $this->_process_subscriber_lists( $lists ); $this->data['is_authorized'] = true; $this->data['custom_fields'] = $this->_fetch_custom_fields(); $this->save_data(); } return $error_message; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $error = esc_html__( 'An error occurred. Please try again later.', 'et_core' ); if ( ! function_exists( 'mailster' ) ) { return $error; } $params = $this->transform_data_to_provider_format( $args, 'subscriber', array( 'dbl_optin' ) ); $params = $this->_process_custom_fields( $params ); $extra_params = array( 'status' => 'disable' === $args['dbl_optin'] ? 1 : 0, 'referrer' => $this->_get_referrer( $args ), ); $params = array_merge( $params, $extra_params ); $subscriber_id = mailster( 'subscribers' )->merge( $params ); if ( is_wp_error( $subscriber_id ) ) { $result = htmlspecialchars_decode( $subscriber_id->get_error_message() ); } else if ( mailster( 'subscribers' )->assign_lists( $subscriber_id, $args['list_id'], false ) ) { $result = 'success'; } else { $result = $error; } return $result; } } PKE\o%%"components/api/email/MailChimp.phpnu[ '-', 'password' => 'api_key', ); /** * @inheritDoc */ public $name = 'MailChimp'; /** * @inheritDoc */ public $slug = 'mailchimp'; public function __construct( $owner, $account_name, $api_key = '' ) { parent::__construct( $owner, $account_name, $api_key ); if ( ! empty( $this->data['api_key'] ) ) { $this->_set_base_url(); } $this->http_auth['username'] = $owner; } protected function _add_note_to_subscriber( $email, $url ) { $email = md5( $email ); $this->prepare_request( "{$url}/$email/notes", 'POST' ); $this->request->BODY = json_encode( array( 'note' => $this->SUBSCRIBED_VIA ) ); $this->make_remote_request(); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $this->response_data_key = 'merge_fields'; $this->prepare_request( "{$this->BASE_URL}/lists/{$list_id}/merge-fields?count={$this->COUNT}" ); $fields = parent::_fetch_custom_fields( $list_id, $list ); foreach ( $fields as $id => $field ) { if ( in_array( $id, array( 1, 2 ) ) ) { unset( $fields[ $id ] ); } } // MailChimp is weird in that they treat checkbox fields as an entirely different concept in their API (Groups) // We'll grab the groups and treat them as checkbox fields in our UI. $groups = $this->_fetch_subscriber_list_groups( $list_id ); return $fields + $groups; } protected function _fetch_subscriber_list_group_options( $list_id, $group_id ) { $this->prepare_request( "{$this->BASE_URL}/lists/{$list_id}/interest-categories/{$group_id}/interests?count={$this->COUNT}" ); $this->make_remote_request(); if ( $this->response->ERROR ) { et_debug( $this->get_error_message() ); return array(); } $data = $this->response->DATA['interests']; $options = array(); foreach ( $data as $option ) { $option = $this->transform_data_to_our_format( $option, 'group_option' ); $id = $option['id']; $options[ $id ] = $option['name']; } return $options; } protected function _fetch_subscriber_list_groups( $list_id ) { $this->response_data_key = 'categories'; $this->prepare_request( "{$this->BASE_URL}/lists/{$list_id}/interest-categories?count={$this->COUNT}" ); $this->make_remote_request(); $groups = array(); if ( false !== $this->response_data_key && empty( $this->response_data_key ) ) { // Let child class handle parsing the response data themselves. return $groups; } if ( $this->response->ERROR ) { et_debug( $this->get_error_message() ); return $groups; } $data = $this->response->DATA[ $this->response_data_key ]; foreach ( $data as $group ) { $group = $this->transform_data_to_our_format( $group, 'group' ); $field_id = $group['field_id']; $type = $group['type']; if ( 'hidden' === $type ) { // MailChimp only allows groups of type: 'checkbox' to be hidden. $group['type'] = 'checkbox'; $group['hidden'] = true; } $group['is_group'] = true; $group['options'] = $this->_fetch_subscriber_list_group_options( $list_id, $field_id ); $group['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'text' ); $groups[ $field_id ] = $group; } return $groups; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; $list_id = self::$_->array_get( $args, 'list_id', '' ); unset( $args['custom_fields'] ); unset( $args['list_id'] ); $custom_fields_data = self::$_->array_get( $this->data, "lists.{$list_id}.custom_fields", array() ); foreach ( $fields as $field_id => $value ) { $is_group = self::$_->array_get( $custom_fields_data, "{$field_id}.is_group", false ); if ( is_array( $value ) && $value ) { foreach ( $value as $id => $field_value ) { if ( $is_group ) { // If it is a group custom field, set as `interests` and don't process the `merge_fields` self::$_->array_set( $args, "interests.{$id}", true ); $field_id = false; } else { $value = $field_value; } } } if ( false === $field_id ) { continue; } // In previous version of Mailchimp implementation we only supported default field tag, but it can be customized and our code fails. // Added `field_tag` attribute which is actual field tag. Fallback to default field tag if `field_tag` doesn't exist for backward compatibility. $custom_field_tag = self::$_->array_get( $custom_fields_data, "{$field_id}.field_tag", "MMERGE{$field_id}" ); // Need to strips existing slash chars. self::$_->array_set( $args, "merge_fields.{$custom_field_tag}", stripslashes( $value ) ); } return $args; } protected function _set_base_url() { $api_key_pieces = explode( '-', $this->data['api_key'] ); $datacenter = empty( $api_key_pieces[1] ) ? '' : $api_key_pieces[1]; $this->BASE_URL = str_replace( '@datacenter@', $datacenter, $this->BASE_URL_PATTERN ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $this->_set_base_url(); /** * The maximum number of subscriber lists to request from MailChimp's API. * * @since 2.0.0 * * @param int $max_lists */ $max_lists = (int) apply_filters( 'et_core_api_email_mailchimp_max_lists', 250 ); $url = "{$this->BASE_URL}/lists?count={$max_lists}&fields=lists.name,lists.id,lists.stats,lists.double_optin"; $this->prepare_request( $url ); $this->response_data_key = 'lists'; $result = parent::fetch_subscriber_lists(); return $result; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'double_optin' => 'double_optin', 'subscribers_count' => 'stats.member_count', ), 'subscriber' => array( 'email' => 'email_address', 'name' => 'merge_fields.FNAME', 'last_name' => 'merge_fields.LNAME', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'detail', ), 'custom_field' => array( 'field_id' => 'merge_id', 'field_tag' => 'tag', 'name' => 'name', 'type' => 'type', 'hidden' => '!public', 'options' => 'options.choices', ), 'custom_field_type' => array( // Us <=> Them 'radio' => 'radio', // Us => Them 'input' => 'text', 'select' => 'dropdown', 'checkbox' => 'checkboxes', // Them => Us 'text' => 'input', 'dropdown' => 'select', 'checkboxes' => 'checkbox', ), 'group' => array( 'field_id' => 'id', 'name' => 'title', 'type' => 'type', ), 'group_option' => array( 'id' => 'id', 'name' => 'name', ), ); return parent::get_data_keymap( $keymap ); } public function get_subscriber( $list_id, $email ) { $hash = md5( strtolower( $email ) ); $this->prepare_request( implode( '/', array( $this->BASE_URL, 'lists', $list_id, 'members', $hash ) ) ); $this->make_remote_request(); return $this->response->STATUS_CODE !== 200 ? null : $this->response->DATA; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $list_id = $args['list_id']; $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); $url = "{$this->BASE_URL}/lists/{$list_id}/members"; $email = $args['email_address']; $err = esc_html__( 'An error occurred, please try later.', 'et_core' ); $dbl_optin = self::$_->array_get( $this->data, "lists.{$list_id}.double_optin", true ); $ip_address = 'true' === self::$_->array_get( $args, 'ip_address', 'true' ) ? et_core_get_ip_address() : '0.0.0.0'; $args['ip_signup'] = $ip_address; $args['status'] = $dbl_optin ? 'pending' : 'subscribed'; $args['list_id'] = $list_id; $args = $this->_process_custom_fields( $args ); $this->prepare_request( $url, 'POST', false, $args, true ); $result = parent::subscribe( $args, $url ); if ( false !== stripos( $result, 'already a list member' ) ) { $result = $err; if ( $user = $this->get_subscriber( $list_id, $email ) ) { if ( 'subscribed' === $user['status'] ) { $result = 'success'; } else { $this->prepare_request( implode( '/', array( $url, $user['id'] ) ), 'PUT', false, $args, true ); $result = parent::subscribe( $args, $url ); } } } if ( 'success' === $result ) { $this->_add_note_to_subscriber( $email, $url ); } else if ( false !== stripos( $result, 'has signed up to a lot of lists ' ) ) { // return message which can be translated. Generic Mailchimp messages are not translatable. $result = esc_html__( 'You have signed up to a lot of lists very recently, please try again later', 'et_core' ); } else { $result = $err; } return $result; } } PKE\..%components/api/email/Infusionsoft.phpnu[ 'client_id', 'api_key' => 'api_key', ); /** * @inheritDoc */ public $ACCESS_TOKEN_URL = 'https://api.infusionsoft.com/token'; /** * @inheritDoc */ public $AUTHORIZATION_URL = 'https://signin.infusionsoft.com/app/oauth/authorize'; /** * @inheritDoc */ public $BASE_URL = ''; /** * @inheritDoc * Use this variable to hold the pattern and update $BASE_URL dynamically when needed */ public $BASE_URL_PATTERN = 'https://@app_name@.infusionsoft.com/api/xmlrpc'; /** * @inheritDoc */ public $custom_fields_scope = 'account'; /** * @inheritDoc */ public $name = 'Infusionsoft'; /** * @inheritDoc */ public $oauth_version = '2.0'; /** * @inheritDoc */ public $slug = 'infusionsoft'; /** * @inheritDoc * @internal If true, oauth endpoints properties must also be defined. */ public $uses_oauth = false; public function __construct( $owner = '', $account_name = '', $api_key = '' ) { parent::__construct( $owner, $account_name, $api_key ); $this->http->expects_json = false; } protected function _add_contact_to_list( $contact_id, $list_id ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], (int) $contact_id, (int) $list_id ); $data = self::$_->prepare_xmlrpc_method_call( 'ContactService.addToGroup', $params ); $this->_do_request( $data ); if ( $this->response->ERROR ) { return false; } return self::$_->process_xmlrpc_response( $this->response->DATA ); } protected function _create_contact( $contact_details ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], $contact_details ); $data = self::$_->prepare_xmlrpc_method_call( 'ContactService.add', $params ); $this->_do_request( $data ); if ( $this->response->ERROR ) { return false; } $result = self::$_->process_xmlrpc_response( $this->response->DATA ); return $result; } protected function _do_request( $data ) { $this->prepare_request( $this->_get_base_url(), 'POST', false, $data ); $this->request->HEADERS = array( 'Content-Type' => 'application/xml', 'Accept-Charset' => 'UTF-8' ); $this->make_remote_request(); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], 'DataFormField', 100, 0, array( 'FormId' => -1 ), array( 'Name', 'Label', 'DataType', 'Values' ) ); $data = self::$_->prepare_xmlrpc_method_call( 'DataService.query', $params ); $this->_do_request( $data ); if ( $this->response->ERROR ) { return array(); } $data = self::$_->process_xmlrpc_response( $this->response->DATA ); foreach ( $data as &$custom_field ) { $custom_field = (array) $custom_field; $custom_field = $this->transform_data_to_our_format( $custom_field, 'custom_field' ); } $fields = array(); foreach ( $data as $field ) { $field_id = $field['field_id']; $type = self::$_->array_get( $field, 'type', 'any' ); $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'any' ); if ( isset( $field['options'] ) ) { $field['options'] = explode( "\n", $field['options'] ); $field['options'] = array_filter( $field['options'] ); } $fields[ $field_id ] = $field; } return $fields; } protected function _get_base_url() { $this->BASE_URL = str_replace( '@app_name@', $this->data[ self::$_data_keys['app_name'] ], $this->BASE_URL_PATTERN ); return $this->BASE_URL; } protected function _get_contact_by_email( $email ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], 'Contact', 1, 0, array( 'Email' => $email ), array( 'Id', 'Groups' ) ); $data = self::$_->prepare_xmlrpc_method_call( 'DataService.query', $params ); $this->_do_request( $data ); if ( $this->response->ERROR ) { return false; } return self::$_->process_xmlrpc_response( $this->response->DATA ); } protected function _optin_email_address( $email ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], $email, $this->SUBSCRIBED_VIA ); $data = self::$_->prepare_xmlrpc_method_call('APIEmailService.optIn', $params ); $this->_do_request( $data ); if ( $this->response->ERROR ) { return false; } return self::$_->process_xmlrpc_response( $this->response->DATA ); } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return array(); } $fields = array(); foreach ( $args['custom_fields'] as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); $value = implode( ',', $value ); } $fields[ "_{$field_id}" ] = $value; } return $fields; } public function retrieve_subscribers_count() { $existing_lists = $this->data['lists']; if ( empty( $existing_lists ) ) { return; } foreach( $existing_lists as $list_id => $list_data ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], 'Contact', array( 'Groups' => "%{$list_id}%" ) ); $data = self::$_->prepare_xmlrpc_method_call( 'DataService.count', $params ); $this->_do_request( $data ); if ( $this->response->ERROR ) { continue; } $subscribers_count = self::$_->process_xmlrpc_response( $this->response->DATA ); if ( empty( $subscribers_count ) || self::$_->is_xmlrpc_error( $subscribers_count ) ) { $subscribers_count = 0; } $existing_lists[ $list_id ]['subscribers_count'] = $subscribers_count; $this->data['lists'] = $existing_lists; $this->save_data(); } } /** * @inheritDoc */ protected function _process_subscriber_lists( $lists ) { $result = array(); if ( empty( $lists ) || ! is_array( $lists ) ) { return $result; } foreach( $lists as $list ) { $list_id = (string) $list->Id; $list_name = (string) $list->GroupName; $result[ $list_id ]['list_id'] = $list_id; $result[ $list_id ]['name'] = $list_name; $result[ $list_id ]['subscribers_count'] = 0; } return $result; } /** * @inheritDoc */ public function get_account_fields() { return array( self::$_data_keys['api_key'] => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), self::$_data_keys['app_name'] => array( 'label' => esc_html__( 'App Name', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'subscriber' => array( 'name' => 'FirstName', 'last_name' => 'LastName', 'email' => 'Email', 'custom_fields' => 'custom_fields', ), 'custom_field' => array( 'field_id' => 'Name', 'name' => 'Label', 'type' => 'DataType', 'options' => 'Values', ), 'custom_field_type' => array( // Us => Them 'input' => 15, 'textarea' => 16, 'checkbox' => 17, 'radio' => 20, 'select' => 21, // Them => Us 15 => 'input', 16 => 'textarea', 17 => 'checkbox', 20 => 'radio', 21 => 'select', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data[ self::$_data_keys['api_key'] ] ) || empty( $this->data[ self::$_data_keys['app_name'] ] ) ) { return $this->API_KEY_REQUIRED; } $this->response_data_key = false; $params_count = array( $this->data[ self::$_data_keys['api_key'] ], 'ContactGroup', array( 'Id' => '%' ) ); $data_count = self::$_->prepare_xmlrpc_method_call( 'DataService.count', $params_count ); $this->_do_request( $data_count ); if ( $this->response->ERROR ) { return $this->response->ERROR_MESSAGE; } $records_count = (int) self::$_->process_xmlrpc_response( $this->http->response->DATA ); if ( 0 === $records_count ) { return 'success'; } // determine how many requests we need to retrieve all lists $number_of_additional_requests = floor( $records_count / 1000 ); $list_data = array(); for ( $i = 0; $i <= $number_of_additional_requests; $i++ ) { $params = array( $this->data[ self::$_data_keys['api_key'] ], 'ContactGroup', 1000, $i, array( 'Id' => '%' ), array( 'Id', 'GroupName' ) ); $data = self::$_->prepare_xmlrpc_method_call( 'DataService.query', $params ); $this->_do_request( $data ); if ( $this->http->response->ERROR ) { return $this->http->response->ERROR_MESSAGE; } $response = self::$_->process_xmlrpc_response( $this->http->response->DATA ); if ( self::$_->is_xmlrpc_error( $response ) ) { return $response->faultString; } $list_data = array_merge( $list_data, $response ); } $lists = $this->_process_subscriber_lists( $list_data ); if ( false === $lists ) { return $this->response->ERROR_MESSAGE; } else if ( self::$_->is_xmlrpc_error( $lists ) ) { return $lists->faultString; } $result = 'success'; $this->data['lists'] = $lists; $this->data['custom_fields'] = $this->_fetch_custom_fields(); $this->data['is_authorized'] = true; // retrieve counts right away if it can be done in reasonable time ( in 20 seconds ) if ( 20 >= count( $lists ) ) { $this->retrieve_subscribers_count(); } else { // estimate the time for all lists update assuming that one list can be updated in 1 second $estimated_time = ceil( count( $lists ) / 60 ); $result = array( 'need_counts_update' => true, 'message' => sprintf( esc_html__( 'Successfully authorized. Subscribers count will be updated in background, please check back in %1$s %2$s', 'et_core' ), $estimated_time, 1 === (int) $estimated_time ? esc_html__( 'minute', 'et_core' ) : esc_html__( 'minutes', 'et_core' ) ), ); } $this->save_data(); return $result; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( empty( $this->data[ self::$_data_keys['api_key'] ] ) || empty( $this->data[ self::$_data_keys['app_name'] ] ) ) { return $this->API_KEY_REQUIRED; } $message = ''; $search_result = $this->_get_contact_by_email( $args['email'] ); if ( false === $search_result ) { return $this->response->ERROR_MESSAGE; } else if ( self::$_->is_xmlrpc_error( $search_result ) ) { return $search_result->faultString; } if ( ! empty( $search_result ) ) { $message = esc_html__( 'Already subscribed', 'bloom' ); if ( false === strpos( $search_result[0]->Groups, $args['list_id'] ) ) { $result = $this->_add_contact_to_list( $search_result[0]->Id, $args['list_id'] ); $message = 'success'; if ( false === $result ) { return $this->response->ERROR_MESSAGE; } else if ( self::$_->is_xmlrpc_error( $result ) ) { return $result->faultString; } } } else { $custom_fields = $this->_process_custom_fields( $args ); $contact_details = array( 'FirstName' => $args['name'], 'LastName' => $args['last_name'], 'Email' => $args['email'], ); $new_contact_id = $this->_create_contact( array_merge( $contact_details, $custom_fields ) ); if ( false === $new_contact_id ) { return $this->response->ERROR_MESSAGE; } else if ( self::$_->is_xmlrpc_error( $new_contact_id ) ) { return $new_contact_id->faultString; } $result = $this->_add_contact_to_list( $new_contact_id, $args['list_id'] ); if ( false === $result ) { return $this->response->ERROR_MESSAGE; } else if ( self::$_->is_xmlrpc_error( $result ) ) { return $search_result->faultString; } if ( $this->_optin_email_address( $args['email'] ) ) { $message = 'success'; } } return ( '' !== $message ) ? $message : $this->FAILURE_MESSAGE; } } PKE\K\components/api/email/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\;] mj%j%"components/api/email/Providers.phpnu[_initialize(); } } protected function _initialize() { self::$_ = ET_Core_Data_Utils::instance(); self::$_metadata = et_core_get_components_metadata(); $third_party_providers = et_core_get_third_party_components( 'api/email' ); $load_fields = is_admin() || et_core_is_saving_builder_modules_cache() || et_core_is_fb_enabled() || isset( $_GET['et_fb'] ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification $all_names = array( 'official' => self::$_metadata['groups']['api/email']['members'], 'third-party' => array_keys( $third_party_providers ), ); $_names_by_slug = array(); $_custom_fields_support = array( 'dynamic' => array(), 'predefined' => array(), 'none' => array() ); $_any_custom_field_type = array(); foreach ( $all_names as $provider_type => $provider_names ) { $_names_by_slug[ $provider_type ] = array(); foreach ( $provider_names as $provider_name ) { if ( 'Fields' === $provider_name || self::$_->includes( $provider_name, 'Provider' ) ) { continue; } if ( 'official' === $provider_type ) { $class_name = self::$_metadata[ $provider_name ]; $provider_slug = self::$_metadata[ $class_name ]['slug']; $provider = $load_fields ? new $class_name( 'ET_Core', '' ) : null; } else { $provider = $third_party_providers[ $provider_name ]; $provider_slug = is_object( $provider ) ? $provider->slug : ''; } if ( ! $provider_slug ) { continue; } $_names_by_slug[ $provider_type ][ $provider_slug ] = $provider_name; if ( $load_fields && is_object( $provider ) ) { self::$_fields[ $provider_slug ] = $provider->get_account_fields(); if ( $scope = $provider->custom_fields ) { $_custom_fields_support[ $scope ][ $provider_slug ] = $provider_name; if ( ! self::$_->array_get( $provider->data_keys, 'custom_field_type' ) ) { $_any_custom_field_type[] = $provider_slug; } } else { $_custom_fields_support['none'][ $provider_slug ] = $provider_name; } } } } /** * Filters the enabled email providers. * * @param array[] { * * @type string[] $provider_type { * * @type string $slug Provider name * } * } */ self::$_names_by_slug = apply_filters( 'et_core_api_email_enabled_providers', $_names_by_slug ); foreach ( array_keys( $all_names ) as $provider_type ) { self::$_names[ $provider_type ] = array_values( self::$_names_by_slug[ $provider_type ] ); self::$_slugs[ $provider_type ] = array_keys( self::$_names_by_slug[ $provider_type ] ); } self::$_name_field_only = self::$_metadata['groups']['api/email']['name_field_only']; self::$_custom_fields_support = $_custom_fields_support; self::$_any_custom_field_type = $_any_custom_field_type; } /** * Returns the email provider accounts array from core. * * @return array|mixed */ public function accounts() { return ET_Core_API_Email_Provider::get_accounts(); } /** * @see {@link \ET_Core_API_Email_Provider::account_exists()} */ public function account_exists( $provider, $account_name ) { return ET_Core_API_Email_Provider::account_exists( $provider, $account_name ); } public function account_fields( $provider = 'all' ) { if ( 'all' !== $provider ) { return isset( self::$_fields[ $provider ] ) ? self::$_fields[ $provider ] : array(); } return self::$_fields; } public function custom_fields_data() { $enabled_providers = self::slugs(); $custom_fields_data = array(); foreach ( $this->accounts() as $provider_slug => $accounts ) { if ( ! in_array( $provider_slug, $enabled_providers ) ) { continue; } foreach ( $accounts as $account_name => $account_details ) { if ( empty( $account_details['lists'] ) ) { continue; } if ( ! empty( $account_details['custom_fields'] ) ) { $custom_fields_data[$provider_slug][$account_name]['custom_fields'] = $account_details['custom_fields']; continue; } foreach ( (array) $account_details['lists'] as $list_id => $list_details ) { if ( ! empty( $list_details['custom_fields'] ) ) { $custom_fields_data[$provider_slug][$account_name][$list_id] = $list_details['custom_fields']; } } } } return $custom_fields_data; } /** * Get class instance for a provider. Instance will be created if necessary. * * @param string $name_or_slug The provider's name or slug. * @param string $account_name The identifier for the desired account with the provider. * @param string $owner The owner for the instance. * * @return bool|ET_Core_API_Email_Provider The provider instance or `false` if not found. */ public function get( $name_or_slug, $account_name, $owner = 'ET_Core' ) { $name_or_slug = str_replace( ' ', '', $name_or_slug ); $is_official = isset( self::$_metadata[ $name_or_slug ] ); if ( ! $is_official && ! $this->is_third_party( $name_or_slug ) ) { return false; } if ( ! in_array( $name_or_slug, array_merge( self::names(), self::slugs() ) ) ) { return false; } // Make sure we have the component name if ( $is_official ) { $class_name = self::$_metadata[ $name_or_slug ]; $name = self::$_metadata[ $class_name ]['name']; } else { $components = et_core_get_third_party_components( 'api/email' ); if ( ! $name = array_search( $name_or_slug, self::$_names_by_slug['third-party'] ) ) { $name = $name_or_slug; } } if ( ! isset( self::$providers[ $name ][ $owner ] ) ) { self::$providers[ $name ][ $owner ] = $is_official ? new $class_name( $owner, $account_name ) : $components[ $name ]; } return self::$providers[ $name ][ $owner ]; } public static function instance() { if ( null === self::$_instance ) { self::$_instance = new self; } return self::$_instance; } public function is_third_party( $name_or_slug ) { $is_third_party = in_array( $name_or_slug, self::$_names['third-party'] ); return $is_third_party ? $is_third_party : in_array( $name_or_slug, self::$_slugs['third-party'] ); } /** * Returns the names of available providers. List can optionally be filtered. * * @param string $type The component type to include ('official'|'third-party'|'all'). Default is 'all'. * * @return array */ public function names( $type = 'all' ) { if ( 'all' === $type ) { $names = array_merge( self::$_names['third-party'], self::$_names['official'] ); } else { $names = self::$_names[ $type ]; } return $names; } /** * Returns an array mapping the slugs of available providers to their names. List can optionally be filtered. * * @param string $type The component type to include ('official'|'third-party'|'all'). Default is 'all'. * @param string $filter Optionally filter the list by a condition. * Accepts 'name_field_only', 'predefined_custom_fields', 'dynamic_custom_fields', * 'no_custom_fields', 'any_custom_field_type', 'custom_fields'. * * @return array */ public function names_by_slug( $type = 'all', $filter = '' ) { if ( 'all' === $type ) { $names_by_slug = array_merge( self::$_names_by_slug['third-party'], self::$_names_by_slug['official'] ); } else { $names_by_slug = self::$_names_by_slug[ $type ]; } if ( 'name_field_only' === $filter ) { $names_by_slug = self::$_name_field_only; } else if ( 'predefined_custom_fields' === $filter ) { $names_by_slug = self::$_custom_fields_support['predefined']; } else if ( 'dynamic_custom_fields' === $filter ) { $names_by_slug = self::$_custom_fields_support['dynamic']; } else if ( 'no_custom_fields' === $filter ) { $names_by_slug = self::$_custom_fields_support['none']; } else if ( 'any_custom_field_type' === $filter ) { $names_by_slug = self::$_any_custom_field_type; } else if ( 'custom_fields' === $filter ) { $names_by_slug = array_merge( self::$_custom_fields_support['predefined'], self::$_custom_fields_support['dynamic'] ); } return $names_by_slug; } /** * @see {@link \ET_Core_API_Email_Provider::remove_account()} */ public function remove_account( $provider, $account_name ) { ET_Core_API_Email_Provider::remove_account( $provider, $account_name ); } /** * Returns the slugs of available providers. List can optionally be filtered. * * @param string $type The component type to include ('official'|'third-party'|'all'). Default is 'all'. * * @return array */ public function slugs( $type = 'all' ) { if ( 'all' === $type ) { $names = array_merge( self::$_slugs['third-party'], self::$_slugs['official'] ); } else { $names = self::$_slugs[ $type ]; } return $names; } /** * @see {@link \ET_Core_API_Email_Provider::update_account()} */ public function update_account( $provider, $account, $data ) { ET_Core_API_Email_Provider::update_account( $provider, $account, $data ); } } PKE\†).).#components/api/email/SalesForce.phpnu[REDIRECT_URL = add_query_arg( 'et-core-api-email-auth', 1, home_url( '', 'https' ) ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change prop name. } else { $this->REDIRECT_URL = admin_url( 'admin.php?page=et_bloom_options', 'https' ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change prop name. } $this->_set_base_url(); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { static $fields = null; $this->response_data_key = 'fields'; $this->prepare_request( "{$this->BASE_URL}/services/data/v39.0/sobjects/Lead/describe" ); if ( is_null( $fields ) ) { $fields = parent::_fetch_custom_fields( $list_id, $list ); foreach ( $fields as $index => $field ) { if ( ! isset( $field['custom'] ) || ! $field['custom'] ) { unset( $fields[ $index ] ); } } } return $fields; } /** * @return string */ protected function _fetch_subscriber_lists() { $query = urlencode( 'SELECT Id, Name, NumberOfLeads from Campaign LIMIT 100' ); $url = "{$this->BASE_URL}/services/data/v39.0/query?q={$query}"; $this->response_data_key = 'records'; $this->prepare_request( $url ); return parent::fetch_subscriber_lists(); } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( 'checkbox' === $this->data['custom_fields'][ $field_id ]['type'] ) { $value = implode( ';', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, "custom_fields.{$field_id}", $value ); } return $args; } public function _set_base_url() { // If we already have the `instance_url`, use it as the base API url. if ( isset( $this->data['instance_url'] ) && ! empty( $this->data['instance_url'] ) ) { $this->BASE_URL = untrailingslashit( $this->data['instance_url'] ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change prop name. } else { $this->BASE_URL = empty( $this->data['login_url'] ) ? '' : untrailingslashit( $this->data['login_url'] ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change prop name. } } public function authenticate() { $this->data['consumer_secret'] = $this->data['client_secret']; $this->data['consumer_key'] = $this->data['api_key']; return parent::authenticate(); } /** * @inheritDoc */ public function get_account_fields() { return array( // SalesForce supports OAuth for SSL websites so generate different fields in this case 'login_url' => array( 'label' => esc_html__( 'Instance URL', 'et_core' ), 'required' => 'https', 'show_if' => array( 'function.protocol' => 'https' ), ), 'api_key' => array( 'label' => esc_html__( 'Consumer Key', 'et_core' ), 'required' => 'https', 'show_if' => array( 'function.protocol' => 'https' ), ), 'client_secret' => array( 'label' => esc_html__( 'Consumer Secret', 'et_core' ), 'required' => 'https', 'show_if' => array( 'function.protocol' => 'https' ), ), // This has to be the last field because is the only one shown in both cases and // CANCEL / SUBMIT buttons will be attached to it. 'organization_id' => array( 'label' => esc_html__( 'Organization ID', 'et_core' ), 'required' => 'http', ), ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { $this->_set_base_url(); // SalesForce supports 2 types of authentication: Simple and OAuth2 if ( isset( $this->data['api_key'], $this->data['client_secret'] ) && ! empty( $this->data['api_key'] ) && ! empty( $this->data['client_secret'] ) ) { // Fetch lists if user already authenticated. if ( $this->is_authenticated() ) { return $this->_fetch_subscriber_lists(); } $authenticated = $this->authenticate(); // If the authenticating process returns an array with redirect url to complete OAuth authorization. if ( is_array( $authenticated ) ) { return $authenticated; } if ( true === $authenticated ) { // Need to reinitialize the OAuthHelper with the new data, to set the authorization header in the next request. $urls = array( 'access_token_url' => $this->ACCESS_TOKEN_URL, // @phpcs:ignore -- No need to change the class property 'request_token_url' => $this->REQUEST_TOKEN_URL, // @phpcs:ignore -- No need to change the class property 'authorization_url' => $this->AUTHORIZATION_URL, // @phpcs:ignore -- No need to change the class property 'redirect_url' => $this->REDIRECT_URL, // @phpcs:ignore -- No need to change the class property ); $this->OAuth_Helper = new ET_Core_API_OAuthHelper( $this->data, $urls, $this->owner ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- No need to change the prop name. return $this->_fetch_subscriber_lists(); } return false; } elseif ( isset( $this->data['organization_id'] ) && '' !== $this->data['organization_id'] ) { // Simple $this->data['is_authorized'] = 'true'; $this->data['lists'] = array( array( 'list_id' => 0, 'name' => 'WebToLead', 'subscribers_count' => 0 ) ); $this->save_data(); // return 'success' immediately in case of simple authentication. Lists cannot be retrieved with this type. return 'success'; } else { return esc_html__( 'Organization ID cannot be empty', 'et_core' ); } } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'Id', 'name' => 'Name', 'subscribers_count' => 'NumberOfLeads', ), 'subscriber' => array( 'name' => 'FirstName', 'last_name' => 'LastName', 'email' => 'Email', 'custom_fields' => 'custom_fields', ), 'custom_field' => array( 'field_id' => 'name', 'name' => 'label', 'type' => 'type', 'options' => 'valueSet', ), 'custom_field_type' => array( // Us => Them 'input' => 'Text', 'textarea' => 'TextArea', 'checkbox' => 'MultiselectPicklist', 'select' => 'Picklist', // Them => Us 'Text' => 'input', 'TextArea' => 'textarea', 'MultiselectPicklist' => 'checkbox', 'Picklist' => 'select', ), ); return parent::get_data_keymap( $keymap ); } public function get_subscriber( $email ) { $query = urlencode( "SELECT Id from Lead where Email='{$email}' LIMIT 100" ); $url = "{$this->BASE_URL}/services/data/v39.0/query?q={$query}"; $this->response_data_key = 'records'; $this->prepare_request( $url ); $this->make_remote_request(); $response = $this->response; if ( $response->ERROR || empty( $response->DATA['records'] ) ) { return false; } return isset( $response->DATA['records'][0]['Id'] ) ? $response->DATA['records'][0]['Id'] : false; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( empty( $this->data['access_secret'] ) ) { // Try to use simple web form return $this->subscribe_salesforce_web( $args ); } $error_message = esc_html__( 'An error occurred. Please try again.', 'et_core' ); $subscriber_id = $this->get_subscriber( $args['email'] ); if ( ! $subscriber_id ) { $url = "{$this->BASE_URL}/services/data/v39.0/sobjects/Lead"; $content = $this->transform_data_to_provider_format( $args, 'subscriber' ); $content = $this->_process_custom_fields( $content ); $content['Company'] = 'Bloom'; if ( isset( $content['custom_fields'] ) && is_array( $content['custom_fields'] ) ) { $content = array_merge( $content, $content['custom_fields'] ); unset( $content['custom_fields'] ); } // The LastName is required by Salesforce, whereas it is possible for Optin Form to not have the last name field. if ( ! isset( $content['LastName'] ) || empty( $content['LastName'] ) ) { $content['LastName'] = '[not provided]'; } $this->prepare_request( $url, 'POST', false, json_encode( $content ), true ); $this->response_data_key = false; $result = parent::subscribe( $content, $url ); if ( 'success' !== $result || empty( $this->response->DATA['id'] ) ) { return $error_message; } $subscriber_id = $this->response->DATA['id']; } $url = "{$this->BASE_URL}/services/data/v39.0/sobjects/CampaignMember"; $content = array( 'LeadId' => $subscriber_id, 'CampaignId' => $args['list_id'], ); $this->prepare_request( $url, 'POST', false, json_encode( $content ), true ); $result = parent::subscribe( $content, $url ); if ( 'success' !== $result && ! empty( $this->response->DATA['errors'] ) ) { return $this->response->DATA['errors'][0]; } else if ( 'success' !== $result ) { return $error_message; } return 'success'; } /** * Post web-to-lead request to SalesForce * * @return string */ public function subscribe_salesforce_web( $args ) { if ( ! isset( $this->data['organization_id'] ) || '' === $this->data['organization_id'] ) { return esc_html__( 'Unknown Organization ID', 'et_core' ); } // Define SalesForce web-to-lead endpoint $url = 'https://webto.salesforce.com/servlet/servlet.WebToLead?encoding=UTF-8'; $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); $args = $this->_process_custom_fields( $args ); // Prepare arguments for web-to-lead POST $form_args = array( 'body' => array( 'oid' => sanitize_text_field( $this->data['organization_id'] ), 'retURL' => esc_url( home_url( '/' ) ), 'email' => sanitize_email( $args['Email'] ), ), ); if ( '' !== $args['FirstName'] ) { $form_args['body']['first_name'] = sanitize_text_field( $args['FirstName'] ); } if ( '' !== $args['LastName'] ) { $form_args['body']['last_name'] = sanitize_text_field( $args['LastName'] ); } if ( isset( $args['custom_fields'] ) && is_array( $args['custom_fields'] ) ) { $form_args = array_merge( $form_args, $args['custom_fields'] ); } // Post to SalesForce web-to-lead endpoint $request = wp_remote_post( $url, $form_args ); if ( ! is_wp_error( $request ) && 200 === wp_remote_retrieve_response_code( $request ) ) { return 'success'; } return esc_html__( 'An error occurred. Please try again.', 'et_core' ); } } PKE\Ncomponents/api/email/init.phpnu[accounts(); foreach ( $all_accounts as $provider_slug => $accounts ) { $provider = $providers->get( $provider_slug, '' ); foreach ( $accounts as $account ) { $provider->set_account_name( $account ); $provider->fetch_subscriber_lists(); } } } endif; if ( ! function_exists( 'et_core_api_email_fetch_lists' ) ): /** * Fetch the latest email lists for a provider account and update the database accordingly. * * @param string $name_or_slug The provider name or slug. * @param string $account The account name. * @param string $api_key Optional. The api key (if fetch succeeds, the key will be saved). * * @return string 'success' if successful, an error message otherwise. */ function et_core_api_email_fetch_lists( $name_or_slug, $account, $api_key = '' ) { if ( ! empty( $api_key ) ) { // The account provided either doesn't exist yet or has a new api key. et_core_security_check( 'manage_options' ); } if ( empty( $name_or_slug ) || empty( $account ) ) { return __( 'ERROR: Invalid arguments.', 'et_core' ); } $providers = ET_Core_API_Email_Providers::instance(); $provider = $providers->get( $name_or_slug, $account, 'builder' ); if ( ! $provider ) { return ''; } if ( is_array( $api_key ) ) { foreach ( $api_key as $field_name => $value ) { $provider->data[ $field_name ] = sanitize_text_field( $value ); } } else if ( '' !== $api_key ) { $provider->data['api_key'] = sanitize_text_field( $api_key ); } return $provider->fetch_subscriber_lists(); } endif; if ( ! function_exists( 'et_core_api_email_providers' ) ): /** * @deprecated {@see ET_Core_API_Email_Providers::instance()} * * @return ET_Core_API_Email_Providers */ function et_core_api_email_providers() { return ET_Core_API_Email_Providers::instance(); } endif; if ( ! function_exists( 'et_core_api_email_remove_account' ) ): /** * Delete an existing provider account. * * @param string $name_or_slug The provider name or slug. * @param string $account The account name. */ function et_core_api_email_remove_account( $name_or_slug, $account ) { et_core_security_check( 'manage_options' ); if ( empty( $name_or_slug ) || empty( $account ) ) { return; } // If the account being removed is a legacy account (pre-dates core api), remove the old data. switch( $account ) { case 'Divi Builder Aweber': et_delete_option( 'divi_aweber_consumer_key' ); et_delete_option( 'divi_aweber_consumer_secret' ); et_delete_option( 'divi_aweber_access_key' ); et_delete_option( 'divi_aweber_access_secret' ); break; case 'Divi Builder Plugin Aweber': $opts = (array) get_option( 'et_pb_builder_options' ); unset( $opts['aweber_consumer_key'], $opts['aweber_consumer_secret'], $opts['aweber_access_key'], $opts['aweber_access_secret'] ); update_option( 'et_pb_builder_options', $opts ); break; case 'Divi Builder MailChimp': et_delete_option( 'divi_mailchimp_api_key' ); break; case 'Divi Builder Plugin MailChimp': $options = (array) get_option( 'et_pb_builder_options' ); unset( $options['newsletter_main_mailchimp_key'] ); update_option( 'et_pb_builder_options', $options ); break; } $providers = ET_Core_API_Email_Providers::instance(); $provider = $providers->get( $name_or_slug, $account ); if ( $provider ) { $provider->delete(); } } endif; PKE\Gdѩ components/api/email/MadMimi.phpnu[_maybe_set_urls(); } protected function _maybe_set_urls( $list_id = '' ) { if ( ! empty( $this->data['api_key'] ) && ! empty( $this->data['username'] ) ) { $args = array( 'username' => rawurlencode( $this->data['username'] ), 'api_key' => $this->data['api_key'], ); $this->LISTS_URL = add_query_arg( $args, $this->LISTS_URL ); $this->SUBSCRIBE_URL = add_query_arg( $args, $this->SUBSCRIBE_URL ); if ( $list_id ) { $this->SUBSCRIBE_URL = str_replace( '@list_id@', rawurlencode( $list_id ), $this->SUBSCRIBE_URL ); } } } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, $field_id, $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'username' => array( 'label' => esc_html__( 'Username', 'et_core' ), ), 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'list_size', ), 'subscriber' => array( 'name' => 'first_name', 'last_name' => 'last_name', 'email' => 'email', 'custom_fields' => 'custom_fields', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) || empty( $this->data['username'] ) ) { return $this->API_KEY_REQUIRED; } $this->_maybe_set_urls(); $this->response_data_key = false; return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { if ( empty( $this->data['api_key'] ) || empty( $this->data['username'] ) ) { return $this->API_KEY_REQUIRED; } $this->_maybe_set_urls( $args['list_id'] ); $ip_address = 'true' === self::$_->array_get( $args, 'ip_address', 'true' ) ? et_core_get_ip_address() : '0.0.0.0'; $args = $this->transform_data_to_provider_format( $args, 'subscriber' ); $args = $this->_process_custom_fields( $args ); $args['ip_address'] = $ip_address; $args['subscribed_via'] = $this->SUBSCRIBED_VIA; $this->SUBSCRIBE_URL = add_query_arg( $args, $this->SUBSCRIBE_URL ); $this->prepare_request( $this->SUBSCRIBE_URL, 'POST', false ); return parent::subscribe( $args, $url ); } } PKE\FT(components/api/email/ConstantContact.phpnu[_maybe_set_custom_headers(); } protected function _create_subscriber_data_array( $args ) { return $this->transform_data_to_provider_format( $args, 'subscriber' ); } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $fields = array(); foreach ( range( 1, 15 ) as $i ) { $fields["custom_field_{$i}"] = array( 'field_id' => "custom_field_{$i}", 'name' => "custom_field_{$i}", 'type' => 'any', ); } return $fields; } protected function _get_list_from_subscriber( $subscriber, $list_id ) { if ( ! isset( $subscriber['lists'] ) ) { return false; } foreach ( $subscriber['lists'] as &$list ) { if ( $list['id'] === $list_id ) { return $list; } } return false; } protected function _maybe_set_custom_headers() { if ( empty( $this->custom_headers ) && isset( $this->data['token'] ) ) { $this->custom_headers = array( 'Authorization' => 'Bearer ' . sanitize_text_field( $this->data['token'] ), ); } } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; $processed_fields = array(); unset( $args['custom_fields'], $this->_subscriber['custom_fields_unprocessed'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } $processed_fields[] = array( 'name' => $field_id, 'value' => $value, ); } if ( isset( $this->_subscriber['custom_fields'] ) ) { $processed_fields = array_merge( $processed_fields, $this->_subscriber['custom_fields'] ); } $this->_subscriber['custom_fields'] = array_unique( $processed_fields, SORT_REGULAR ); return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), 'token' => array( 'label' => esc_html__( 'Access Token', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'contact_count', ), 'subscriber' => array( 'name' => 'first_name', 'last_name' => 'last_name', 'email' => 'email_addresses.[0].email_address', 'list_id' => 'lists.[0].id', 'custom_fields' => 'custom_fields_unprocessed', ), 'error' => array( 'error_message' => '[0].error_message', ), 'custom_field' => array( 'field_id' => 'name', 'name' => 'name', ), ); return parent::get_data_keymap( $keymap ); } public function get_subscriber( $email ) { $url = add_query_arg( 'email', $email, $this->SUBSCRIBERS_URL ); $this->prepare_request( $url, 'GET', false ); $this->make_remote_request(); if ( $this->response->ERROR || ! isset( $this->response->DATA['results'] ) ) { return array(); } return $this->response->DATA['results']; } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) || empty( $this->data['token'] ) ) { return $this->API_KEY_REQUIRED; } $this->_maybe_set_custom_headers(); $this->response_data_key = false; $this->LISTS_URL = add_query_arg( 'api_key', $this->data['api_key'], $this->LISTS_URL ); return parent::fetch_subscriber_lists(); } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $this->SUBSCRIBERS_URL = add_query_arg( 'api_key', $this->data['api_key'], $this->SUBSCRIBERS_URL ); $result = null; $args['list_id'] = (string) $args['list_id']; $subscriber = $this->get_subscriber( $args['email'] ); $subscriber = $subscriber ? $subscriber[0] : $subscriber; $query_args = array( 'api_key' => $this->data['api_key'], 'action_by' => 'ACTION_BY_VISITOR' ); if ( $subscriber ) { if ( $list = $this->_get_list_from_subscriber( $subscriber, $args['list_id'] ) ) { $result = 'success'; } else { $subscriber['lists'][] = array( 'id' => $args['list_id'] ); $this->_subscriber = &$subscriber; $args = $this->_process_custom_fields( $args ); $url = add_query_arg( $query_args, "{$this->SUBSCRIBE_URL}/{$subscriber['id']}" ); $this->prepare_request( $url, 'PUT', false, $subscriber, true ); } } else { $url = add_query_arg( $query_args, $this->SUBSCRIBE_URL ); $subscriber = $this->_create_subscriber_data_array( $args ); $this->_subscriber = &$subscriber; $args = $this->_process_custom_fields( $args ); $this->prepare_request( $url, 'POST', false, $subscriber, true ); } if ( 'success' !== $result ) { $result = parent::subscribe( $args, $this->SUBSCRIBE_URL ); } return $result; } } PKE\\Q0%%#components/api/email/ConvertKit.phpnu[LISTS_URL = "{$this->BASE_URL}/forms"; } protected function _fetch_custom_fields( $list_id = '', $list = array() ) { $this->response_data_key = 'custom_fields'; $this->prepare_request( $this->_generate_url_for_request( "{$this->BASE_URL}/custom_fields" ) ); return parent::_fetch_custom_fields( $list_id, $list ); } /** * Generates the URL for adding subscribers. * * @param $list_id * * @since 1.1.0 * * @return string */ protected function _get_subscribe_url( $list_id ) { return "{$this->LISTS_URL}/{$list_id}/subscribe"; } protected function _get_subscriber_counts( $forms ) { $result = array(); foreach ( (array) $forms as $form_info ) { $url = $this->_generate_url_for_request( "{$this->LISTS_URL}/{$form_info['id']}/subscriptions", true ); $this->prepare_request( $url ); $this->make_remote_request(); if ( $this->response->ERROR || ! isset( $this->response->DATA['total_subscriptions'] ) ) { continue; } $form_info['total_subscriptions'] = $this->response->DATA['total_subscriptions']; $result[] = $form_info; } return $result; } /** * Adds default args for all API requests to given url. * * @since 1.1.0 * * @param string $url * @param bool $with_secret * * @return string */ protected function _generate_url_for_request( $url, $with_secret = false ) { $key = $with_secret ? $this->data['api_secret'] : $this->data['api_key']; $key_type = $with_secret ? 'api_secret' : 'api_key'; return esc_url_raw( add_query_arg( $key_type, $key, $url ) ); } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( count( $value ) > 1 ) { $value = implode( ',', $value ); } else { $value = array_pop( $value ); } } self::$_->array_set( $args, "fields.{$field_id}", $value ); } return $args; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), 'api_secret' => array( 'label' => esc_html__( 'API Secret', 'et_core' ), ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'total_subscriptions', ), 'subscriber' => array( 'email' => 'email', 'name' => 'first_name', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'message', ), 'custom_field' => array( 'field_id' => 'key', 'name' => 'label', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) ) { return $this->API_KEY_REQUIRED; } $url = $this->_generate_url_for_request( $this->LISTS_URL ); $result = 'success'; $this->response_data_key = ''; $this->prepare_request( $url ); parent::fetch_subscriber_lists(); if ( ! $this->response->ERROR && ! empty( $this->response->DATA['forms'] ) ) { /** * We need to store `$forms` to avoid using mutated `$this->response->DATA['forms']` down the line. * * `$this->response->DATA['forms']` will be mutated to `NULL` in this code block since it is a shared state * and is used by other functions all over. This fixes the issue. * * @see: https://github.com/elegantthemes/Divi/issues/25296 */ $forms = $this->response->DATA['forms']; $with_subscriber_counts = $this->_get_subscriber_counts( $forms ); $this->data['lists'] = $this->_process_subscriber_lists( $with_subscriber_counts ); $this->data['is_authorized'] = 'true'; $this->data['custom_fields'] = $this->_fetch_custom_fields( '', array_shift( $forms ) ); $this->save_data(); } elseif ( $this->response->ERROR ) { $result = $this->get_error_message(); } return $result; } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { $url = $this->_generate_url_for_request( $this->_get_subscribe_url( $args['list_id'] ) ); $params = $this->transform_data_to_provider_format( $args, 'subscriber' ); $params = $this->_process_custom_fields( $params ); $params['fields']['notes'] = $this->SUBSCRIBED_VIA; $this->prepare_request( $url, 'POST', false, $params ); return parent::subscribe( $params, $url ); } } PKE\!Ն&components/api/email/_ProviderName.phpnu[ array( 'list_id' => '', 'name' => '', 'subscribers_count' => '', ), 'subscriber' => array( 'name' => '', 'email' => '', 'list_id' => '', 'ip_address' => '', ), ); return parent::get_data_keymap( $keymap, $custom_fields_key ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { // Implement get_subscriber_lists() method. } /** * @inheritDoc */ public function subscribe( $args, $url = '' ) { // Implement subscribe() method. } } PKE\w8 'components/api/email/ActiveCampaign.phpnu[ array( 'field_id' => '%phone%', 'hidden' => false, 'name' => 'Phone', 'type' => 'input', ), '%customer_acct_name%' => array( 'field_id' => '%customer_acct_name%', 'hidden' => false, 'name' => 'Account', 'type' => 'input', ), ); foreach ( $list['fields'] as $field ) { $field = $this->transform_data_to_our_format( $field, 'custom_field' ); $field_id = $field['field_id']; $type = $field['type']; $field['type'] = self::$_->array_get( $this->data_keys, "custom_field_type.{$type}", 'text' ); if ( isset( $field['options'] ) ) { $options = array(); foreach ( $field['options'] as $option ) { $option = $this->transform_data_to_our_format( $option, 'custom_field_option' ); $id = $option['id']; $options[ $id ] = $option['name']; } $field['options'] = $options; } $fields[ $field_id ] = $field; } return $fields; } protected function _process_custom_fields( $args ) { if ( ! isset( $args['custom_fields'] ) ) { return $args; } $fields = $args['custom_fields']; unset( $args['custom_fields'] ); foreach ( $fields as $field_id => $value ) { if ( is_array( $value ) && $value ) { // This is a multiple choice field (eg. checkbox, radio, select) $value = array_values( $value ); if ( 'checkbox' === $this->data['custom_fields'][ $field_id ]['type'] ) { $value = implode( '||', $value ); $value = "||{$value}||"; } else { $value = array_pop( $value ); } } // Check if the custom field is an ActiveCampaign general field, // it should be posted as dedicated param instead of `field[{$field_id},0]` param. if ( preg_match( '/%(.*)%/', $field_id, $matches ) ) { self::$_->array_set( $args, $matches[1], $value ); } else { self::$_->array_set( $args, "field[{$field_id},0]", $value ); } } return $args; } /** * Returns the requests URL for the account assigned to this class instance. * * @return string */ protected function _get_requests_url() { $base_url = untrailingslashit( $this->data['api_url'] ); return "{$base_url}/admin/api.php"; } /** * @inheritDoc */ public function get_account_fields() { return array( 'api_key' => array( 'label' => esc_html__( 'API Key', 'et_core' ), ), 'api_url' => array( 'label' => esc_html__( 'API URL', 'et_core' ), 'apply_password_mask' => false, ), 'form_id' => array( 'label' => esc_html__( 'Form ID', 'et_core' ), 'not_required' => true, 'apply_password_mask' => false, ), ); } /** * @inheritDoc */ public function get_data_keymap( $keymap = array() ) { $keymap = array( 'list' => array( 'list_id' => 'id', 'name' => 'name', 'subscribers_count' => 'subscriber_count', ), 'subscriber' => array( 'email' => 'email', 'last_name' => 'last_name', 'name' => 'first_name', 'custom_fields' => 'custom_fields', ), 'error' => array( 'error_message' => 'result_message', ), 'custom_field' => array( 'field_id' => 'id', 'name' => 'title', 'type' => 'type', 'hidden' => '!visible', 'options' => 'options', ), 'custom_field_option' => array( 'id' => 'value', 'name' => 'name', ), 'custom_field_type' => array( // Us <=> Them 'checkbox' => 'checkbox', 'radio' => 'radio', 'textarea' => 'textarea', 'hidden' => 'hidden', // Us => Them 'select' => 'dropdown', 'input' => 'text', // Them => Us 'dropdown' => 'select', 'text' => 'input', ), ); return parent::get_data_keymap( $keymap ); } /** * @inheritDoc */ public function fetch_subscriber_lists() { if ( empty( $this->data['api_key'] ) || empty( $this->data['api_url'] ) ) { return $this->API_KEY_REQUIRED; } $query_args = array( 'api_key' => $this->data['api_key'], 'api_action' => 'list_list', 'api_output' => 'json', 'ids' => 'all', 'full' => '1', 'global_fields' => '1', ); $request_url = add_query_arg( $query_args, $this->_get_requests_url() ); $request_url = esc_url_raw( $request_url, array( 'https' ) ); $this->prepare_request( $request_url ); $this->request->HEADERS['Content-Type'] = 'application/x-www-form-urlencoded'; parent::fetch_subscriber_lists(); if ( $this->response->ERROR ) { return $this->get_error_message(); } $lists = array(); foreach ( $this->response->DATA as $key => $list_data ) { if ( ! is_numeric( $key ) ) { continue; } if ( ! empty( $list_data ) ) { $lists[] = $list_data; } } $this->data['lists'] = $this->_process_subscriber_lists( $lists ); $this->data['custom_fields'] = $this->_fetch_custom_fields( '', array_shift( $this->response->DATA ) ); $this->data['is_authorized'] = 'true'; $this->save_data(); et_debug($this->data); return 'success'; } /** * Get ActiveCampaign subscriber info by email. * * @param string $email * * @return array */ public function get_subscriber( $email ) { $query_args = array( 'api_key' => $this->data['api_key'], 'api_action' => 'subscriber_view_email', 'api_output' => 'json', 'email' => $email, ); // Build request URL. This action only accept GET method. $request_url = add_query_arg( $query_args, $this->_get_requests_url() ); $request_url = esc_url_raw( $request_url, array( 'https' ) ); // Prepare and send the request. $this->prepare_request( $request_url ); $this->request->HEADERS['Content-Type'] = 'application/x-www-form-urlencoded'; $this->make_remote_request(); // Ensure no error happen and it's included in one of the lists. $list_id = self::$_->array_get( $this->response->DATA, 'listid', false ); $result_code = self::$_->array_get( $this->response->DATA, 'result_code', false ); if ( $this->response->ERROR || ! $list_id || ! $result_code ) { return false; } return $this->response->DATA; } /** * @inheritDoc */ public function subscribe( $args, $url= '' ) { // Ensure to skip subscribe action if current email already subscribed. $subscriber_data = $this->get_subscriber( $args['email'] ); $subscriber_lists = self::$_->array_get( $subscriber_data, 'lists', array() ); $subscriber_list = self::$_->array_get( $subscriber_lists, $args['list_id'], false ); if ( $subscriber_list ) { return 'success'; } $list_id_key = 'p[' . $args['list_id'] . ']'; $status_key = 'status[' . $args['list_id'] . ']'; $responders_key = 'instantresponders[' . $args['list_id'] . ']'; $list_id = $args['list_id']; $args = $this->transform_data_to_provider_format( $args, 'subscriber', array( 'list_id' ) ); $args = $this->_process_custom_fields( $args ); $query_args = array( 'api_key' => $this->data['api_key'], 'api_action' => 'contact_sync', 'api_output' => 'json', ); $url = esc_url_raw( add_query_arg( $query_args, $this->_get_requests_url() ) ); $args[ $list_id_key ] = $list_id; $args[ $status_key ] = 1; $args[ $responders_key ] = 1; if ( ! empty( $this->data['form_id'] ) ) { $args['form'] = (int) $this->data['form_id']; } $this->prepare_request( $url, 'POST', false, $args ); $this->request->HEADERS['Content-Type'] = 'application/x-www-form-urlencoded'; return parent::subscribe( $args, $url ); } } PKE\_ۇ..!components/api/social/Network.phpnu[service_type = 'social'; parent::__construct( $owner, $account_name ); } /** * @inheritDoc */ protected function _get_data_keys() { // Implement _get_data_keys() method. } /** * @inheritDoc */ public function get_account_fields() { // Implement get_fields() method. } /** * @inheritDoc */ protected function _get_accounts_data() { // Implement _get_accounts_data() method. } /** * @inheritDoc */ public function get_data_keymap( $keymap = array(), $custom_fields_key = '' ) { // Implement get_data_keymap() method. } /** * @inheritDoc */ public function save_data() { // Implement save_data() method. } }PKE\K\components/api/social/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\lQ""components/api/OAuthHelper.phpnu[_initialize( $data, $urls ); $this->sha1_method = new ET_Core_LIB_OAuthHMACSHA1(); $this->consumer = new ET_Core_LIB_OAuthConsumer( $this->consumer_key, $this->consumer_secret ); if ( '' !== $this->access_token && '' !== $this->access_token_secret ) { $this->token = new ET_Core_LIB_OAuthToken( $this->access_token, $this->access_token_secret ); } else if ( empty( $this->access_token ) && ! empty( $this->access_token_secret ) ) { $this->bearer = "Bearer {$this->access_token_secret}"; } } /** * @internal * * @param array $data {@see self::__construct()} * @param array $urls {@see self::__construct()} */ private function _initialize( $data, $urls ) { $this->consumer_key = isset( $data['consumer_key'] ) ? $data['consumer_key'] : ''; $this->consumer_secret = isset( $data['consumer_secret'] ) ? $data['consumer_secret'] : ''; $this->access_token = isset( $data['access_key'] ) ? $data['access_key'] : ''; $this->access_token_secret = isset( $data['access_secret'] ) ? $data['access_secret'] : ''; $this->REQUEST_TOKEN_URL = $urls['request_token_url']; $this->AUTHORIZATION_URL = $urls['authorization_url']; $this->ACCESS_TOKEN_URL = $urls['access_token_url']; $this->REDIRECT_URL = isset( $urls['redirect_url'] ) ? $urls['redirect_url'] : ''; } protected function _get_oauth2_parameters( $args ) { et_core_nonce_verified_previously(); return wp_parse_args( $args, array( 'grant_type' => 'authorization_code', 'code' => sanitize_text_field( $_GET['code'] ), 'client_id' => $this->consumer_key, 'client_secret' => $this->consumer_secret, 'redirect_uri' => $this->REDIRECT_URL, ) ); } /** * @param \ET_Core_HTTPRequest $request * * @return \ET_Core_HTTPRequest */ protected function _prepare_oauth_request( $request ) { $parameters = array(); if ( is_array( $request->BODY ) && $request->BODY && ! $request->JSON_BODY ) { $parameters = $request->BODY; } $oauth_request = ET_Core_LIB_OAuthRequest::from_consumer_and_token( $this->consumer, $this->token, $request->METHOD, $request->URL, $parameters ); $oauth_request->sign_request( $this->sha1_method, $this->consumer, $this->token ); if ( 'GET' === $request->METHOD ) { $request->URL = $oauth_request->to_url(); } else if ( 'POST' === $request->METHOD ) { $request->URL = $request->JSON_BODY ? $oauth_request->to_url() : $oauth_request->get_normalized_http_url(); $request->BODY = $request->JSON_BODY ? json_encode( $request->BODY ) : $oauth_request->to_post_data(); } return $request; } /** * @param \ET_Core_HTTPRequest $request * * @return \ET_Core_HTTPRequest */ protected function _prepare_oauth2_request( $request ) { if ( null !== $this->bearer ) { $request->HEADERS['Authorization'] = $this->bearer; } if ( $request->JSON_BODY ) { return $request; } if ( is_array( $request->BODY ) && ! array_key_exists( 'code', $request->BODY ) ) { $request->URL = add_query_arg( $request->BODY, $request->URL ); $request->BODY = null; } return $request; } /** * Finish the OAuth2 authorization process if needed. */ public static function finish_oauth2_authorization() { et_core_nonce_verified_previously(); if ( ! isset( $_GET['state'] ) || 0 !== strpos( $_GET['state'], 'ET_Core' ) ) { return; } list( $_, $name, $account, $nonce ) = explode( '|', sanitize_text_field( rawurldecode( $_GET['state'] ) ) ); if ( ! $name || ! $account || ! $nonce ) { return; } $_GET['nonce'] = $nonce; et_core_security_check( 'manage_options', 'et_core_api_service_oauth2', 'nonce', '_GET' ); $providers = et_core_api_email_providers(); if ( ! $providers->account_exists( $name, $account ) ) { et_core_die(); } if ( ! $provider = $providers->get( $name, $account, 'ET_Core' ) ) { et_core_die(); } $result = $provider->fetch_subscriber_lists(); // Display the authorization results echo et_core_esc_previously( ET_Bloom::generate_modal_warning( $result ) ); } /** * Prepare a request for an access token. * * @param array $args { * For OAuth 1.0 & 1.0a: * * @type string $verifier OAuth verifier token. Optional. * * For OAuth 2.0: * * @type string $code The code returned when the user was redirected back to their dashboard. * @type string $grant_type The desired grant type, as per the OAuth 2.0 spec. * @type string $redirect_uri The redirect URL from the original authorization request. * } * * @return ET_Core_HTTPRequest */ public function prepare_access_token_request( $args = array() ) { et_core_nonce_verified_previously(); $oauth2 = ! empty( $_GET['code'] ); $request = new ET_Core_HTTPRequest( $this->ACCESS_TOKEN_URL, 'POST', '', true ); $request->BODY = $oauth2 ? $this->_get_oauth2_parameters( $args ) : $args; return $this->prepare_oauth_request( $request, $oauth2 ); } /** * Prepare an OAuth 1.0a or 2.0 request. * * @param ET_Core_HTTPRequest $request * @param bool $oauth2 * * @return \ET_Core_HTTPRequest */ function prepare_oauth_request( $request, $oauth2 = false ) { return $oauth2 ? $this->_prepare_oauth2_request( $request ) : $this->_prepare_oauth_request( $request ); } /** * Process a response to an OAuth access token request and retrieve the access token if auth was successful. * * @param \ET_Core_HTTPResponse $response */ public function process_authentication_response( $response, $json = true ) { if ( $response->ERROR ) { return; } $response = $json ? $response->DATA : wp_parse_args( $response->DATA ); // Salesforce returns an `instance_url` data in the auth response. if ( isset( $response['instance_url'] ) ) { $this->INSTANCE_URL = esc_url( $response['instance_url'] ); // @phpcs:ignore ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase -- Use uppercase to be consistent with existing code. } if ( isset( $response['oauth_token'], $response['oauth_token_secret'] ) ) { // OAuth 1.0a $token = sanitize_text_field( $response['oauth_token'] ); $secret = sanitize_text_field( $response['oauth_token_secret'] ); $this->token = new ET_Core_LIB_OAuthToken( $token, $secret ); } elseif ( isset( $response['access_token'] ) ) { // OAuth 2.0 $this->token = new ET_Core_LIB_OAuthToken( '', sanitize_text_field( $response['access_token'] ) ); if ( isset( $response['refresh_token'] ) ) { $this->token->refresh_token = sanitize_text_field( $response['refresh_token'] ); } } } } PKE\@n#components/CompatibilityWarning.phpnu[ '5.3.0', 'theme' => '5.5.0', ); /** * Class constructor. */ public function __construct() { global $wp_version; // Ensure the system is loaded on lower version of supported version. if ( version_compare( $wp_version, $this->supported_wp_version[ ET_CORE_TYPE ], '>=' ) ) { return; } add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); // A. Update Core - Overrides plugins and themes updates table body. add_action( 'admin_print_footer_scripts-update-core.php', array( $this, 'overrides_update_core_plugins_table_body' ) ); add_action( 'admin_print_footer_scripts-update-core.php', array( $this, 'overrides_update_core_themes_table_body' ) ); // B. Manage Themes - Overrides themes list & details templates. add_filter( 'wp_prepare_themes_for_js', array( $this, 'set_theme_additional_properties' ) ); add_action( 'admin_print_footer_scripts-themes.php', array( $this, 'overrides_tmpl_theme' ) ); // C. Theme Customizer - Overrides themes list & details templates. add_action( 'customize_controls_print_footer_scripts', array( $this, 'overrides_tmpl_customize_control_theme_content' ) ); // D. Plugins - Overrides current plugin list. Default priority is 20. add_action( 'load-plugins.php', array( $this, 'overrides_plugins_table_rows' ), 21 ); } /** * Returns instance of the class. * * @since 4.7.0 * * @return ET_Core_CompatibilityWarning */ public static function instance() { if ( ! isset( self::$instance_class ) ) { self::$instance_class = new self(); } return self::$instance_class; } /** * Set theme additional properties before it's rendered on Manage Themes page. * * @since 4.7.0 * * @param array $prepared_themes List of available themes. * * @return array */ public function set_theme_additional_properties( $prepared_themes ) { // Bail early if the $prepared_themes is empty. if ( empty( $prepared_themes ) ) { return $prepared_themes; } // 1. Get available themes update. $theme_updates = array(); if ( current_user_can( 'update_themes' ) ) { $updates_themes_transient = get_site_transient( 'update_themes' ); if ( isset( $updates_themes_transient->response ) ) { $theme_updates = $updates_themes_transient->response; } } // 2. Assign compatibility properties. $themes = $prepared_themes; foreach ( $themes as $theme_slug => $theme_info ) { // Ensure style.css file exist. $theme_root = get_theme_root( $theme_slug ); $theme_file = "{$theme_root}/{$theme_slug}/style.css"; if ( ! file_exists( $theme_file ) ) { continue; } // Get WP & PHP compatibility info. $theme_headers = get_file_data( $theme_file, array( 'RequiresWP' => 'Requires at least', 'RequiresPHP' => 'Requires PHP', ), 'theme' ); $require_wp = et_()->array_get( $theme_headers, 'RequiresWP', null ); $require_php = et_()->array_get( $theme_headers, 'RequiresPHP', null ); $update_requires_wp = et_()->array_get( $theme_updates, array( $theme_slug, 'requires' ), null ); $update_requires_php = et_()->array_get( $theme_updates, array( $theme_slug, 'requires_php' ), null ); $compatibility_properties = array( 'compatibleWP' => is_wp_version_compatible( $require_wp ), 'compatiblePHP' => is_php_version_compatible( $require_php ), 'updateResponse' => array( 'compatibleWP' => is_wp_version_compatible( $update_requires_wp ), 'compatiblePHP' => is_php_version_compatible( $update_requires_php ), ), ); $prepared_themes[ $theme_slug ] = array_merge( $prepared_themes[ $theme_slug ], $compatibility_properties ); } return $prepared_themes; } /** * Get plugins data for Update Core page. * * The data processing is backported from WP 5.5 with few modification. * * @see {list_plugin_updates()} of WP 5.5 * * @since 4.7.0 * * @return array */ public function get_update_core_plugins_data() { $plugin_updates = get_plugin_updates(); $plugin_processed = array(); // Bail early if there is no plugin updates. if ( empty( $plugin_updates ) ) { return array(); } foreach ( $plugin_updates as $plugin_file => $plugin_data ) { // reason: The properties come from WP plugin data. // phpcs:disable ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase $plugin_name = $plugin_data->Name; $plugin_version = $plugin_data->Version; // phpcs:enable // a. Get current and update WP version. $wp_version = get_bloginfo( 'version' ); $cur_wp_version = preg_replace( '/-.*$/', '', $wp_version ); $core_updates = get_core_updates(); if ( ! isset( $core_updates[0]->response ) || 'latest' === $core_updates[0]->response || 'development' === $core_updates[0]->response || version_compare( $core_updates[0]->current, $cur_wp_version, '=' ) ) { $core_update_version = false; } else { $core_update_version = $core_updates[0]->current; } // b. Check PHP versions compatibility. WP doesn't check WP versions compatibility. $requires_php = isset( $plugin_data->update->requires_php ) ? $plugin_data->update->requires_php : null; $compatible_php = is_php_version_compatible( $requires_php ); // c. Icon. $icon = ''; $preferred_icons = array( 'svg', '2x', '1x', 'default' ); foreach ( $preferred_icons as $preferred_icon ) { if ( ! empty( $plugin_data->update->icons[ $preferred_icon ] ) ) { $icon = ''; break; } } // d. Process compatibility warning text. // Get plugin compat for running version of WordPress. if ( isset( $plugin_data->update->tested ) && version_compare( $plugin_data->update->tested, $cur_wp_version, '>=' ) ) { /* translators: %s: WordPress version. */ $compat = '
    ' . sprintf( __( 'Compatibility with WordPress %s: 100%% (according to its author)' ), $cur_wp_version ); } else { /* translators: %s: WordPress version. */ $compat = '
    ' . sprintf( __( 'Compatibility with WordPress %s: Unknown' ), $cur_wp_version ); } // Get plugin compat for updated version of WordPress. if ( $core_update_version ) { if ( isset( $plugin_data->update->tested ) && version_compare( $plugin_data->update->tested, $core_update_version, '>=' ) ) { /* translators: %s: WordPress version. */ $compat .= '
    ' . sprintf( __( 'Compatibility with WordPress %s: 100%% (according to its author)' ), $core_update_version ); } else { /* translators: %s: WordPress version. */ $compat .= '
    ' . sprintf( __( 'Compatibility with WordPress %s: Unknown' ), $core_update_version ); } } // Get plugin compat for updated version of PHP. if ( ! $compatible_php && current_user_can( 'update_php' ) ) { $compat .= '
    ' . __( 'This update doesn’t work with your version of PHP.' ) . ' '; $compat .= sprintf( /* translators: %s: URL to Update PHP page. */ __( 'Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); $annotation = wp_get_update_php_annotation(); if ( $annotation ) { $compat .= '

    ' . $annotation . ''; } } // Get the upgrade notice for the new plugin version. if ( isset( $plugin_data->update->upgrade_notice ) ) { $upgrade_notice = '
    ' . wp_strip_all_tags( $plugin_data->update->upgrade_notice ); } else { $upgrade_notice = ''; } $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $plugin_data->update->slug . '§ion=changelog&TB_iframe=true&width=640&height=662' ); $details = sprintf( '%3$s', esc_url( $details_url ), /* translators: 1: Plugin name, 2: Version number. */ esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $plugin_data->update->new_version ) ), /* translators: %s: Plugin version. */ sprintf( __( 'View version %s details.' ), $plugin_data->update->new_version ) ); $checkbox_id = 'checkbox_' . md5( $plugin_name ); // Plugin template properties. There is no compatible_wp property passed here. $plugin_processed[ $plugin_file ] = array( 'plugin_file' => esc_attr( $plugin_file ), 'name' => esc_attr( $plugin_name ), 'checkbox_id' => esc_attr( 'checkbox_' . md5( $plugin_name ) ), 'icon' => et_core_intentionally_unescaped( $icon, 'html' ), 'version' => esc_attr( $plugin_version ), 'new_version' => esc_attr( $plugin_data->update->new_version ), 'compatible_php' => $compatible_php, 'compat' => et_core_intentionally_unescaped( $compat, 'html' ), 'upgrade_notice' => et_core_intentionally_unescaped( $upgrade_notice, 'html' ), 'details' => et_core_intentionally_unescaped( $details, 'html' ), ); } return $plugin_processed; } /** * Get themes data for Update Core page. * * @since 4.7.0 * * @return array */ public function get_update_core_themes_data() { $theme_updates = get_theme_updates(); $theme_processed = array(); // Bail early if there is no theme updates. if ( empty( $theme_updates ) ) { return array(); } foreach ( $theme_updates as $stylesheet => $theme ) { // a. Check compatibility. $requires_wp = et_()->array_get( $theme->update, 'requires', null ); $requires_php = et_()->array_get( $theme->update, 'requires_php', null ); $compatible_wp = is_wp_version_compatible( $requires_wp ); $compatible_php = is_php_version_compatible( $requires_php ); // b. Process compatibility warning text. $compat = ''; if ( ! $compatible_wp && ! $compatible_php ) { $compat .= '
    ' . __( 'This update doesn’t work with your versions of WordPress and PHP.' ) . ' '; if ( current_user_can( 'update_core' ) && current_user_can( 'update_php' ) ) { $compat .= sprintf( /* translators: 1: URL to WordPress Updates screen, 2: URL to Update PHP page. */ __( 'Please update WordPress, and then learn more about updating PHP.' ), esc_url( self_admin_url( 'update-core.php' ) ), esc_url( wp_get_update_php_url() ) ); $annotation = wp_get_update_php_annotation(); if ( $annotation ) { $compat .= '

    ' . $annotation . ''; } } elseif ( current_user_can( 'update_core' ) ) { $compat .= sprintf( /* translators: %s: URL to WordPress Updates screen. */ __( 'Please update WordPress.' ), esc_url( self_admin_url( 'update-core.php' ) ) ); } elseif ( current_user_can( 'update_php' ) ) { $compat .= sprintf( /* translators: %s: URL to Update PHP page. */ __( 'Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); $annotation = wp_get_update_php_annotation(); if ( $annotation ) { $compat .= '

    ' . $annotation . ''; } } } elseif ( ! $compatible_wp ) { $compat .= '
    ' . __( 'This update doesn’t work with your version of WordPress.' ) . ' '; if ( current_user_can( 'update_core' ) ) { $compat .= sprintf( /* translators: %s: URL to WordPress Updates screen. */ __( 'Please update WordPress.' ), esc_url( self_admin_url( 'update-core.php' ) ) ); } } elseif ( ! $compatible_php ) { $compat .= '
    ' . __( 'This update doesn’t work with your version of PHP.' ) . ' '; if ( current_user_can( 'update_php' ) ) { $compat .= sprintf( /* translators: %s: URL to Update PHP page. */ __( 'Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); $annotation = wp_get_update_php_annotation(); if ( $annotation ) { $compat .= '

    ' . $annotation . ''; } } } // Theme template properties. $theme_processed[ $stylesheet ] = array( 'stylesheet' => esc_attr( $stylesheet ), 'name' => esc_attr( $theme->display( 'Name' ) ), 'checkbox_id' => esc_attr( 'checkbox_' . md5( $theme->get( 'Name' ) ) ), 'screenshot' => esc_url( $theme->get_screenshot() ), 'version' => esc_attr( $theme->display( 'Version' ) ), 'new_version' => esc_attr( et_()->array_get( $theme->update, 'new_version', '' ) ), 'compatible_wp' => $compatible_wp, 'compatible_php' => $compatible_php, 'compat' => et_core_esc_previously( $compat ), ); } return $theme_processed; } /** * Enqueue compatibility warning scripts and its local data. * * @since 4.7.0 */ public function enqueue_scripts() { global $pagenow, $wp_customize; // Bail early if the current page is not one of the allowed pages. $allowed_pages = array( 'update-core.php', 'customize.php', 'themes.php', ); if ( ! in_array( $pagenow, $allowed_pages, true ) ) { return; } // Enqueue main scripts. wp_enqueue_script( 'et_compatibility_warning_script', ET_CORE_URL . 'admin/js/compatibility-warning.js', array( 'jquery' ), ET_CORE_VERSION, true ); $compatibility_warning = array(); if ( 'update-core.php' === $pagenow ) { $compatibility_warning['update_core_data'] = array( 'plugins' => self::get_update_core_plugins_data(), 'themes' => self::get_update_core_themes_data(), ); } elseif ( 'themes.php' === $pagenow ) { $compatibility_warning['manage_themes_data'] = true; } elseif ( 'customize.php' === $pagenow ) { // Ensure style.css file exist. $theme_root = $wp_customize->theme()->theme_root; $theme_slug = $wp_customize->theme()->stylesheet; $theme_file = "{$theme_root}/{$theme_slug}/style.css"; // Get WP & PHP compatibility info. $theme_headers = array(); if ( file_exists( $theme_file ) ) { $theme_headers = get_file_data( $theme_file, array( 'RequiresWP' => 'Requires at least', 'RequiresPHP' => 'Requires PHP', ), 'theme' ); } $requires_wp = et_()->array_get( $theme_headers, 'RequiresWP', false ); $requires_php = et_()->array_get( $theme_headers, 'RequiresPHP', false ); // Theme Customizer - Used for disable publish button. $compatibility_warning['customizer_data'] = array( 'compatible_wp' => is_wp_version_compatible( $requires_wp ), 'compatible_php' => is_php_version_compatible( $requires_php ), 'disabled_text' => esc_html_x( 'Cannot Activate', 'theme' ), ); } wp_localize_script( 'et_compatibility_warning_script', 'et_compatibility_warning', $compatibility_warning ); } /** * Overrides table body of plugin updates section. * * The structure is backported from WP 5.5 without any modification. * * @see {list_plugin_updates()} of WP 5.5 * * @since 4.7.0 */ public function overrides_update_core_plugins_table_body() { // Bail early if there is no plugin updates. if ( empty( get_plugin_updates() ) ) { return; } ?> response ) && is_array( $update_plugins->response ) ) { foreach ( $update_plugins->response as $plugin_file => $plugin ) { $requires_php = isset( $plugin->requires_php ) ? $plugin->requires_php : null; $compatible_php = is_php_version_compatible( $requires_php ); // Bail early if the package empty or already compatible with current PHP version. if ( empty( $plugin->package ) || $compatible_php ) { continue; } // Need to remove default action before we can replace it with the new one. remove_action( "after_plugin_row_$plugin_file", 'wp_plugin_update_row', 10, 2 ); add_action( "after_plugin_row_$plugin_file", array( $this, 'plugin_update_row_compatibility_error' ), 10, 2 ); } } } /** * Display plugin update row with error compatibility. * * @see {wp_plugin_update_row()} of WP 5.5 * * @since 4.7.0 * * @param string $file Plugin basename. * @param array $plugin_data Plugin information. */ public function plugin_update_row_compatibility_error( $file, $plugin_data ) { if ( ! is_network_admin() && is_multisite() ) { return; } $update_plugins = get_site_transient( 'update_plugins' ); if ( ! isset( $update_plugins->response[ $file ] ) ) { return; } // a. Plugin response. $response = $update_plugins->response[ $file ]; // b. Plugin name. $plugins_allowedtags = array( 'a' => array( 'href' => array(), 'title' => array(), ), 'abbr' => array( 'title' => array() ), 'acronym' => array( 'title' => array() ), 'code' => array(), 'em' => array(), 'strong' => array(), ); $plugin_name = wp_kses( $plugin_data['Name'], $plugins_allowedtags ); // c. Details URL. $details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . $response->slug . '§ion=changelog&TB_iframe=true&width=600&height=800' ); // d. Active class. if ( is_network_admin() ) { $active_class = is_plugin_active_for_network( $file ) ? ' active' : ''; } else { $active_class = is_plugin_active( $file ) ? ' active' : ''; } /** * Column count. * * @var WP_Plugins_List_Table $wp_list_table */ $wp_list_table = _get_list_table( 'WP_Plugins_List_Table', array( 'screen' => get_current_screen(), ) ); // f. Error text. $update_php_notation = wp_get_update_php_annotation(); $error_text = sprintf( /* translators: 1: Plugin name, 2: Details URL, 3: Additional link attributes, 4: Version number 5: URL to Update PHP page. */ __( 'There is a new version of %1$s available, but it doesn’t work with your version of PHP. View version %4$s details or learn more about updating PHP. %6$s' ), $plugin_name, esc_url( $details_url ), sprintf( 'class="thickbox open-plugin-details-modal" aria-label="%s"', /* translators: 1: Plugin name, 2: Version number. */ esc_attr( sprintf( __( 'View %1$s version %2$s details' ), $plugin_name, $response->new_version ) ) ), esc_attr( $response->new_version ), esc_url( wp_get_update_php_url() ), // #5 ! empty( $update_php_notation ) ? sprintf( __( '
    %s' ), $update_php_notation ) : '' ); printf( /* translators: 1: Active class, 2: Update slug, 3: Slug, 4: Plugin file, 5: Column count. */ '

    %6$s

    ', esc_attr( $active_class ), esc_attr( $response->slug . '-update' ), esc_attr( $response->slug ), esc_attr( $file ), esc_attr( $wp_list_table->get_column_count() ), // #5 et_core_intentionally_unescaped( $error_text, 'html' ) ); } /** * Overrides theme info & details display of Theme Customizer. * * The structure is backported from WP 5.5 without any modification. * * @see {WP_Customize_Theme_Control::content_template()} of WP 5.5 * * @since 4.7.0 */ public function overrides_tmpl_customize_control_theme_content() { /* translators: %s: Theme name. */ $details_label = sprintf( esc_html__( 'Details for theme: %s' ), '{{ data.theme.name }}' ); /* translators: %s: Theme name. */ $customize_label = sprintf( esc_html__( 'Customize theme: %s' ), '{{ data.theme.name }}' ); /* translators: %s: Theme name. */ $preview_label = sprintf( esc_html__( 'Live preview theme: %s' ), '{{ data.theme.name }}' ); /* translators: %s: Theme name. */ $install_label = sprintf( esc_html__( 'Install and preview theme: %s' ), '{{ data.theme.name }}' ); ?> 'Plugin Name', 'RequiresWP' => 'Requires at least', 'RequiresPHP' => 'Requires PHP', ), 'plugin' ); $requirements = array( 'requires' => ! empty( $plugin_headers['RequiresWP'] ) ? $plugin_headers['RequiresWP'] : '', 'requires_php' => ! empty( $plugin_headers['RequiresPHP'] ) ? $plugin_headers['RequiresPHP'] : '', ); if ( ! function_exists( 'is_wp_version_compatible' ) || ! function_exists( 'is_php_version_compatible' ) ) { require_once plugin_dir_path( $plugin_file ) . 'core/wp_functions.php'; } // Check version compatibility. $compatible_wp = is_wp_version_compatible( $requirements['requires'] ); $compatible_php = is_php_version_compatible( $requirements['requires_php'] ); /* translators: %s: URL to Update PHP page. */ $php_update_message = '

    ' . sprintf( __( 'Learn more about updating PHP.' ), esc_url( wp_get_update_php_url() ) ); $annotation = wp_get_update_php_annotation(); if ( $annotation ) { $php_update_message .= '

    ' . $annotation . ''; } // Decide whether current plugin is compatible and should be activated or not. $result = true; if ( ! $compatible_wp && ! $compatible_php ) { $result = new WP_Error( 'plugin_wp_php_incompatible', '

    ' . sprintf( /* translators: 1: Current WordPress version, 2: Current PHP version, 3: Plugin name, 4: Required WordPress version, 5: Required PHP version. */ _x( 'Error: Current versions of WordPress (%1$s) and PHP (%2$s) do not meet minimum requirements for %3$s. The plugin requires WordPress %4$s and PHP %5$s.', 'plugin' ), get_bloginfo( 'version' ), phpversion(), $plugin_headers['Name'], $requirements['requires'], $requirements['requires_php'] ) . $php_update_message . '

    ' ); } elseif ( ! $compatible_php ) { $result = new WP_Error( 'plugin_php_incompatible', '

    ' . sprintf( /* translators: 1: Current PHP version, 2: Plugin name, 3: Required PHP version. */ _x( 'Error: Current PHP version (%1$s) does not meet minimum requirements for %2$s. The plugin requires PHP %3$s.', 'plugin' ), phpversion(), $plugin_headers['Name'], $requirements['requires_php'] ) . $php_update_message . '

    ' ); } elseif ( ! $compatible_wp ) { $result = new WP_Error( 'plugin_wp_incompatible', '

    ' . sprintf( /* translators: 1: Current WordPress version, 2: Plugin name, 3: Required WordPress version. */ _x( 'Error: Current WordPress version (%1$s) does not meet minimum requirements for %2$s. The plugin requires WordPress %3$s.', 'plugin' ), get_bloginfo( 'version' ), $plugin_headers['Name'], $requirements['requires'] ) . '

    ' ); } if ( is_wp_error( $result ) ) { wp_die( $result ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Can't call et_core_intentionally_unescaped function because it's fired during plugin activation hook. } } } endif; PKE\HHcomponents/VersionRollback.phpnu[product_name = sanitize_text_field( $product_name ); $this->product_shortname = sanitize_text_field( $product_shortname ); $this->product_version = sanitize_text_field( $product_version ); if ( ! $options = get_site_option( 'et_automatic_updates_options' ) ) { $options = get_option( 'et_automatic_updates_options' ); } $this->api_username = isset( $options['username'] ) ? sanitize_text_field( $options['username'] ) : ''; $this->api_key = isset( $options['api_key'] ) ? sanitize_text_field( $options['api_key'] ) : ''; } /** * Enqueue assets. * * @since ?.? Script `et-core-version-rollback` now loads in footer. * @since 3.10 */ public function assets() { wp_enqueue_style( 'et-core-version-rollback', ET_CORE_URL . 'admin/css/version-rollback.css', array( 'et-core-admin', ), ET_CORE_VERSION ); wp_enqueue_script( 'et-core-version-rollback', ET_CORE_URL . 'admin/js/version-rollback.js', array( 'jquery', 'jquery-ui-tabs', 'jquery-form', 'et-core-admin', ), ET_CORE_VERSION, true ); wp_localize_script( 'et-core-version-rollback', 'etCoreVersionRollbackI18n', array( 'unknownError' => esc_html__( 'An unknown error has occurred. Please try again later.', 'et-core' ), ) ); } /** * Get previous installed version, if any. * * @since 3.10 * * @return string */ protected function _get_previous_installed_version() { return et_get_option( "{$this->product_shortname}_previous_installed_version", '' ); } /** * Set previous installed version. * * @since 3.10 * * @param string $version * * @return void */ protected function _set_previous_installed_version( $version ) { et_update_option( "{$this->product_shortname}_previous_installed_version", sanitize_text_field( $version ) ); } /** * Get latest installed version, if any. * * @since 3.10 * * @return string */ protected function _get_latest_installed_version() { return et_get_option( "{$this->product_shortname}_latest_installed_version", '' ); } /** * Set latest installed version. * * @since 3.10 * * @param string $version * * @return void */ protected function _set_latest_installed_version( $version ) { et_update_option( "{$this->product_shortname}_latest_installed_version", sanitize_text_field( $version ) ); } /** * Check if the product has already been rolled back. * * @since 3.10 * * @return bool */ protected function _is_rolled_back() { return version_compare( $this->_get_latest_installed_version(), $this->_get_previous_installed_version(), '<=' ); } /** * Get unique ajax action. * * @since 3.10 * * @return string */ protected function _get_ajax_action() { return 'et_core_version_rollback'; } /** * Enable update rollback. * * @since 3.10 * * @return void */ public function enable() { if ( $this->enabled ) { return; } $this->enabled = true; add_action( 'admin_enqueue_scripts', array( $this, 'assets' ) ); add_action( 'wp_ajax_' . $this->_get_ajax_action(), array( $this, 'ajax_rollback' ) ); // Update version number when theme is manually replaced. add_action( 'admin_init', array( $this, 'store_previous_version_number' ) ); // Update version number when theme is activated. add_action( 'after_switch_theme', array( $this, 'store_previous_version_number' ) ); // Update version number when theme is updated. add_action( 'upgrader_process_complete', array( $this, 'store_previous_version_number' ), 10, 0 ); } /** * Handle REST API requests to rollback. * * @since 3.10 * * @return void */ public function ajax_rollback() { if ( ! isset( $_GET['nonce'] ) || ! wp_verify_nonce( $_GET['nonce'], $this->_get_ajax_action() ) ) { wp_send_json_error( array( 'errorCode' => 'et_unknown', 'error' => esc_html__( 'Security check failed. Please refresh and try again.', 'et-core' ), ), 400 ); } if ( ! current_user_can( 'install_themes' ) ) { wp_send_json_error( array( 'errorCode' => 'et_unknown', 'error' => esc_html__( 'You don\'t have sufficient permissions to access this page.', 'et-core' ), ), 400 ); } if ( $this->_is_rolled_back() ) { $error = '

    ' . et_get_safe_localization( sprintf( __( 'You\'re currently rolled back to Version %1$s from Version %2$s.', 'et-core' ), esc_html( $this->_get_latest_installed_version() ), esc_html( $this->_get_previous_installed_version() ) ) ) . '

    ' . et_get_safe_localization( sprintf( __( 'Update to the latest version to unlock the full power of %1$s. Learn more here.', 'et-core' ), esc_html( $this->product_name ), esc_url( $this->_get_update_documentation_url() ) ) ) . '

    '; wp_send_json_error( array( 'errorCode' => 'et_unknown', 'error' => $error, ), 400 ); } $success = $this->rollback(); if ( is_wp_error( $success ) ) { $error = $success->get_error_message(); if ( $success->get_error_code() === 'et_version_rollback_blocklisted' ) { $error = '

    ' . et_get_safe_localization( sprintf( __( 'For privacy and security reasons, you cannot rollback to Version %1$s.', 'et-core' ), esc_html( $this->_get_previous_installed_version() ) ) ) . '

    ' . esc_html__( 'Learn more here.', 'et-core' ) . '

    '; } wp_send_json_error( array( 'errorIsUnrecoverable' => in_array( $success->get_error_code(), array( 'et_version_rollback_not_available', 'et_version_rollback_blocklisted' ) ), 'errorCode' => $success->get_error_code(), 'error' => $error, ), 400 ); } wp_send_json_success(); } /** * Execute a version rollback. * * @since 3.10 * * @return bool|WP_Error */ public function rollback() { // Load versions before rollback so they are not affected. $previous_version = $this->_get_previous_installed_version(); $latest_version = $this->_get_latest_installed_version(); $api = new ET_Core_API_ElegantThemes( $this->api_username, $this->api_key ); $available = $api->is_product_available( $this->product_name, $previous_version ); if ( is_wp_error( $available ) ) { $major_minor = implode( '.', array_slice( explode( '.', $previous_version ), 0, 2 ) ); if ( $major_minor . '.0' === $previous_version ) { // Skip the trailing 0 in the version number and retry. $previous_version = $major_minor; $available = $api->is_product_available( $this->product_name, $previous_version ); } if ( is_wp_error( $available ) ) { return $available; } } $download_url = $api->get_download_url( $this->product_name, $previous_version ); // Buffer and discard output as upgrader classes still output content even if the upgrader skin is silent. $buffer_started = ob_start(); $result = $this->_install_theme( $download_url ); if ( $buffer_started ) { ob_end_clean(); } if ( is_wp_error( $result ) ) { return $result; } if ( true !== $result ) { return new WP_Error( 'et_unknown', esc_html__( 'An unknown error has occurred. Please try again later.', 'et-core' ) ); } /** * Fires after successful product version rollback. * * @since 3.26 * * @param string $product_short_name - The short name of the product rolling back. * @param string $rollback_from_version - The product version rolling back from. * @param string $rollback_to_version - The product version rolling back to. */ do_action( 'et_after_version_rollback', $this->product_shortname, $latest_version, $previous_version ); // Swap version numbers after a successful rollback. $this->_set_previous_installed_version( $latest_version ); $this->_set_latest_installed_version( $previous_version ); } /** * Install a theme overwriting it if it already exists. * Copied from Theme_Upgrader::install() due to lack of control over the clear_desination argument. * * @see Theme_Upgrader::install() @ WordPress 4.9.4 * * @since 3.10 * * @param string $package * * @return bool|WP_Error */ protected function _install_theme( $package ) { require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); $upgrader = new Theme_Upgrader( new ET_Core_LIB_SilentThemeUpgraderSkin() ); $defaults = array( 'clear_update_cache' => true, ); $parsed_args = wp_parse_args( array(), $defaults ); $upgrader->init(); $upgrader->install_strings(); add_filter('upgrader_source_selection', array( $upgrader, 'check_package' ) ); add_filter('upgrader_post_install', array( $upgrader, 'check_parent_theme_filter' ), 10, 3 ); if ( $parsed_args['clear_update_cache'] ) { // Clear cache so wp_update_themes() knows about the new theme. add_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9, 0 ); } $upgrader->run( array( 'package' => $package, 'destination' => get_theme_root(), 'clear_destination' => true, // Overwrite theme. 'clear_working' => true, 'hook_extra' => array( 'type' => 'theme', 'action' => 'install', ), ) ); remove_action( 'upgrader_process_complete', 'wp_clean_themes_cache', 9 ); remove_filter( 'upgrader_source_selection', array( $upgrader, 'check_package' ) ); remove_filter( 'upgrader_post_install', array( $upgrader, 'check_parent_theme_filter' ) ); if ( ! $upgrader->result || is_wp_error( $upgrader->result ) ) { return $upgrader->result; } // Refresh the Theme Update information. wp_clean_themes_cache( $parsed_args['clear_update_cache'] ); return true; } /** * Get update documentation url for the product. * * @since 3.10 * * @return string */ protected function _get_update_documentation_url() { return "https://www.elegantthemes.com/documentation/{$this->product_shortname}/update-{$this->product_shortname}/"; } /** * Return ePanel option. * * @since 3.10 * * @return array */ public function get_epanel_option() { return array( 'name' => esc_html__( 'Version Rollback', 'et-core' ), 'id' => 'et_version_rollback', 'type' => 'callback_function', 'function_name' => array( $this, 'render_epanel_option' ), 'desc' => et_get_safe_localization( __( 'If you recently updated to a new version and are experiencing problems, you can easily roll back to the previously-installed version. We always recommend using the latest version and testing updates on a staging site. However, if you run into problems after updating you always have the option to roll back.', 'et-core' ) ), ); } /** * Render ePanel option. * * @since 3.10 * * @return void */ public function render_epanel_option() { $previous = $this->_get_previous_installed_version(); $modal_renderer = array( $this, 'render_epanel_no_previous_version_modal' ); if ( ! empty( $previous ) ) { $modal_renderer = array( $this, 'render_epanel_confirm_rollback_modal' ); if ( $this->_is_rolled_back() ) { $modal_renderer = array( $this, 'render_epanel_already_rolled_back_modal' ); } } add_action( 'admin_footer', $modal_renderer ); ?>

    product_name ) ); ?>

    _get_ajax_action(); $url = add_query_arg( array( 'action' => $action, 'nonce' => wp_create_nonce( $action ), ), admin_url( 'admin-ajax.php' ) ); ?>

    Version %1$s from the current Version %2$s.', 'et-core' ), esc_html( $this->_get_previous_installed_version() ), esc_html( $this->_get_latest_installed_version() ) ) ); ?>

    Learn more here.', 'et-core' ), esc_html( $this->product_name ), esc_url( $this->_get_update_documentation_url() ) ) ); ?>

    Version %1$s from Version %2$s.', 'et-core' ), esc_html( $this->_get_latest_installed_version() ), esc_html( $this->_get_previous_installed_version() ) ) ); ?>

    Learn more here.', 'et-core' ), esc_html( $this->product_name ), esc_url( $this->_get_update_documentation_url() ) ) ); ?>

    _get_previous_installed_version(); $latest_installed_version = $this->_get_latest_installed_version(); // Get the theme version since the files may have changed but // we are still executing old code from memory. $theme_version = et_get_theme_version(); if ( $latest_installed_version === $theme_version ) { return; } if ( empty( $latest_installed_version ) ) { $latest_installed_version = $theme_version; } if ( version_compare( $theme_version, $latest_installed_version, '!=') ) { $previous_installed_version = $latest_installed_version; $latest_installed_version = $theme_version; } /** * Fires after new version number is updated. * * @since 4.10.0 */ do_action( 'et_store_before_new_version_update' ); $this->_set_previous_installed_version( $previous_installed_version ); $this->_set_latest_installed_version( $latest_installed_version ); /** * Fires after new version number is updated. * * @since 4.10.0 */ do_action( 'et_store_after_new_version_update' ); } } endif; PKE\}J]](components/SupportCenterMUAutoloader.phpnu[ * @license GNU General Public License v2 */ // The general idea here is loosely based on . // Quick exit if accessed directly if ( ! defined( 'ABSPATH' ) ) { exit; } // We only want to load these MU Plugins if Support Center is installed $support_center_installed = get_option( 'et_support_center_installed' ); if ( $support_center_installed ) { // Compile a list of plugins in the `mu-plugins/et-safe-mode` directory // (see `$pathname_to` in `ET_Core_SupportCenter::maybe_add_mu_autoloader()`) if ( $mu_plugins = glob( dirname( __FILE__ ) . '/et-safe-mode/*.php' ) ) { // Verbose logging: only log if `wp-config.php` has defined `ET_DEBUG='support_center'` $DEBUG_ET_SUPPORT_CENTER = defined( 'ET_DEBUG' ) && 'support_center' === ET_DEBUG; // Loop through the list of plugins and require each in turn foreach ( $mu_plugins as $plugin ) { if ( file_exists( $plugin ) ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center: loading mu-plugin: ' . $plugin ); } require_once( $plugin ); } } } } PKE\YԨcomponents/Updates.phpnu[core_url = $core_url; $this->version = '1.2'; $this->up_to_date_products_data = array(); $this->product_version = $product_version; $this->get_options(); $this->upgrading_et_product = false; $this->update_product_domains(); $this->maybe_force_update_requests(); add_filter( 'wp_prepare_themes_for_js', array( $this, 'replace_theme_update_notification' ) ); add_filter( 'upgrader_package_options', array( $this, 'check_upgrading_product' ) ); // The 4th parameter, $hook_extra was added in WordPress 5.5.0. if ( version_compare( $wp_version, '5.5.0', '>=' ) ) { add_filter( 'upgrader_pre_download', array( $this, 'update_error_message' ), 20, 4 ); } else { add_filter( 'upgrader_pre_download', array( $this, 'update_error_message' ), 20, 3 ); } add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_plugins_updates' ) ); add_filter( 'plugins_api', array( $this, 'maybe_modify_plugins_changelog' ), 20, 3 ); add_filter( 'pre_set_site_transient_update_themes', array( $this, 'check_themes_updates' ) ); add_filter( 'self_admin_url', array( $this, 'change_plugin_changelog_url' ), 10, 2 ); add_filter( 'admin_url', array( $this, 'change_plugin_changelog_url' ), 10, 2 ); add_filter( 'network_admin_url', array( $this, 'change_plugin_changelog_url' ), 10, 2 ); add_action( 'admin_notices', array( $this, 'maybe_show_account_notice' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'load_scripts_styles' ) ); add_action( 'plugins_loaded', array( $this, 'remove_updater_plugin_actions' ), 30 ); add_action( 'after_setup_theme', array( $this, 'remove_theme_update_actions' ), 11 ); add_action( 'admin_init', array( $this, 'remove_plugin_update_actions' ) ); add_action( 'update_site_option_et_automatic_updates_options', array( $this, 'force_update_requests' ) ); add_action( 'update_option_et_automatic_updates_options', array( $this, 'force_update_requests' ) ); add_action( 'deleted_site_transient', array( $this, 'maybe_reset_et_products_update_transient' ) ); add_action( 'upgrader_process_complete', array( $this, 'upgraded_a_product' ), 9, 0 ); } function check_upgrading_product( $options ) { if ( ! isset( $options['hook_extra'] ) ) { return $options; } $hook_name = isset( $options['hook_extra']['plugin'] ) ? 'plugin' : 'theme'; // set the upgrading_et_product flag if one of ET plugins or themes is about to upgrade if ( isset( $options['hook_extra'][ $hook_name ] ) && in_array( $options['hook_extra'][ $hook_name ], $this->all_et_products_domains[ $hook_name ] ) ) { $this->upgrading_et_product = true; } return $options; } function maybe_append_custom_notification( $plugin_data, $response ) { if ( empty( $response ) ) { $package_available = false; } else { // for themes response is array for plugins - object, so check the format of data to get the correct results $package_available = is_array( $response ) ? ! empty( $response['package'] ) : ! empty( $response->package ); } if ( $package_available ) { return; } $message = empty( $custom_message = $this->get_custom_update_notification_message( $plugin_data['url'] ) ) ? et_get_safe_localization( __( 'For all Elegant Themes products, please authenticate your subscription via the Updates tab in your theme & plugin settings to enable product updates. Make sure that your Username and API Key have been entered correctly.', 'et-core' ) ) : $custom_message; echo "

    {$message}"; } /** * Check if we need to force update options removal in case a customer clicked on "Check Again" button * in the notification area. */ function maybe_force_update_requests() { if ( wp_doing_ajax() ) { return; } if ( empty( $_GET['et_action'] ) || 'update_account_details' !== $_GET['et_action'] ) { return; } if ( empty( $_GET['et_update_account_details_nonce'] ) || ! wp_verify_nonce( $_GET['et_update_account_details_nonce'], 'et_update_account_details' ) ) { return; } $this->force_update_requests(); } function get_custom_update_notification_message( $update_message ) { $is_valid_api_key_status = empty( $account_api_key_status = get_site_option( 'et_account_api_key_status' ) ) || 'invalid' !== $account_api_key_status; if ( $is_valid_api_key_status && false !== strpos( $update_message, '/wp-json/api/v1/changelog/product_id/' ) ) { return et_get_safe_localization( __( 'The license for this Divi Marketplace product has expired. Please renew the license to continue receiving product updates and support.', 'et-core' ) ); } if ( false !== strpos( $update_message, 'Automatic update is unavailable for this theme' ) ) { return 'expired' === $this->account_status ? et_get_safe_localization( __( 'Your Elegant Themes subscription has expired. You must renew your account to regain access to product updates and support.', 'et-core' ) ) : et_get_safe_localization( __( 'Before you can receive product updates, you must first authenticate your Elegant Themes subscription. To do this, you need to enter both your Elegant Themes Username and your Elegant Themes API Key into the Updates Tab in your theme and plugin settings. To locate your API Key, log in to your Elegant Themes account and navigate to the Account > API Key page. Learn more here. If you still get this message, please make sure that your Username and API Key have been entered correctly', 'et-core' ) ); } return ''; } function replace_theme_update_notification( $themes_array ) { if ( empty( $themes_array ) ) { return $themes_array; } if ( empty( $this->all_et_products_domains['theme'] ) ) { return $themes_array; } foreach ( $themes_array as $id => $theme_data ) { // replace default error message with custom message for ET themes. if ( ! in_array( $id, $this->all_et_products_domains['theme'] ) || false === strpos( $theme_data['update'], 'Automatic update is unavailable for this theme' ) ) { continue; } if ( ! empty( $custom_message = $this->get_custom_update_notification_message( $theme_data['update'] ) ) ) { $themes_array[ $id ]['update'] = sprintf( '

    %1$s
    %2$s

    ', $theme_data['update'], $custom_message ); } } return $themes_array; } function update_error_message( $reply, $package, $upgrader, $hook_extra = array() ) { if ( ! $this->upgrading_et_product ) { return $reply; } // reset the upgrading_et_product flag $this->upgrading_et_product = false; if ( ! empty( $package ) ) { return $reply; } $hook_name = ! empty( $hook_extra['theme'] ) ? 'theme' : 'plugin'; $site_transient = 'theme' === $hook_name ? get_site_transient( 'et_update_themes' ) : get_site_transient( 'et_update_plugins' ); $changelog_url = ''; if ( isset( $site_transient->response ) && ! empty( $site_transient->response[ $hook_extra[ $hook_name ] ] ) ) { $changelog_url = 'theme' === $hook_name ? $site_transient->response[ $hook_extra[ $hook_name ] ]['url'] : $site_transient->response[ $hook_extra[ $hook_name ] ]->url; } if ( false !== strpos( $changelog_url, '/wp-json/api/v1/changelog/product_id/' ) ) { $error_message = $this->get_custom_update_notification_message( $changelog_url ); } else { $error_message = 'expired' === $this->account_status ? et_get_safe_localization( __( 'Your Elegant Themes subscription has expired. You must renew your account to regain access to product updates and support.', 'et-core' ) ) : et_get_safe_localization( __( 'Before you can receive product updates, you must first authenticate your Elegant Themes subscription. To do this, you need to enter both your Elegant Themes Username and your Elegant Themes API Key into the Updates Tab in your theme and plugin settings. To locate your API Key, log in to your Elegant Themes account and navigate to the Account > API Key page. Learn more here. If you still get this message, please make sure that your Username and API Key have been entered correctly', 'et-core' ) ); } // output custom error message for ET Products if package is empty return new WP_Error( 'no_package', $error_message ); } /** * Get all Elegant Themes products, returned from the API request */ function get_et_api_products() { $products = array( 'theme' => array(), 'plugin' => array(), ); $update_transients = array( 'et_update_themes', 'et_update_plugins', ); foreach ( $update_transients as $update_transient_name ) { $type = 'et_update_themes' === $update_transient_name ? 'theme' : 'plugin'; if ( false !== ( $update_transient = get_site_transient( $update_transient_name ) ) && ! empty( $update_transient->response ) && is_array( $update_transient->response ) ) { $et_product_stylesheet_names = array_keys( $update_transient->response ); foreach ( $et_product_stylesheet_names as $et_product_stylesheet_name ) { $products[ $type ][] = $et_product_stylesheet_name; } } } return $products; } function get_all_et_products() { $checked_et_products = $this->get_et_api_products(); return $checked_et_products; } function remove_theme_update_actions() { remove_filter( 'pre_set_site_transient_update_themes', 'et_check_themes_updates' ); remove_filter( 'site_transient_update_themes', 'et_add_themes_to_update_notification' ); } function remove_plugin_update_actions() { remove_filter( 'pre_set_site_transient_update_plugins', 'et_shortcodes_plugin_check_updates' ); remove_filter( 'site_transient_update_plugins', 'et_shortcodes_plugin_add_to_update_notification' ); } /** * Removes Updater plugin actions and filters, * so it doesn't make additional requests to API * * @return void */ function remove_updater_plugin_actions() { if ( ! class_exists( 'ET_Automatic_Updates' ) ) { return; } $updates_class = ET_Automatic_Updates::get_this(); remove_filter( 'after_setup_theme', array( $updates_class, 'remove_default_updates' ), 11 ); remove_filter( 'init', array( $updates_class, 'remove_default_plugins_updates' ), 20 ); remove_action( 'admin_notices', array( $updates_class, 'maybe_display_expired_message' ) ); } /** * Returns an instance of the object * * @return object */ static function get_this() { return self::$_this; } /** * Adds automatic updates data only if Username and API key options are set * * @param array $send_to_api Data sent to server * @return array Modified data set if Username and API key are set, original data if not */ function maybe_add_automatic_updates_data( $send_to_api ) { if ( $this->options && isset( $this->options['username'] ) && isset( $this->options['api_key'] ) ) { $send_to_api['automatic_updates'] = 'on'; $send_to_api['username'] = urlencode( sanitize_text_field( $this->options['username'] ) ); $send_to_api['api_key'] = sanitize_text_field( $this->options['api_key'] ); $send_to_api = apply_filters( 'et_add_automatic_updates_data', $send_to_api ); } return $send_to_api; } /** * Gets plugin options * * @return void */ function get_options() { if ( ! $this->options = get_site_option( 'et_automatic_updates_options' ) ) { $this->options = get_option( 'et_automatic_updates_options' ); } if ( ! $this->account_status = get_site_option( 'et_account_status' ) ) { $this->account_status = get_option( 'et_account_status' ); } } function load_scripts_styles( $hook ) { if ( 'plugin-install.php' !== $hook ) { return; } wp_enqueue_style( 'et_core_updates', $this->core_url . 'admin/css/updates.css', array(), $this->product_version ); } function add_up_to_date_products_data( $update_data, $settings = array() ) { $settings = $this->process_request_settings( $settings ); $products_category = $settings['is_plugin_response'] ? 'plugins' : 'themes'; if ( ! empty( $this->up_to_date_products_data[ $products_category ] ) ) { $update_data->no_update = $this->up_to_date_products_data[ $products_category ]; } return $update_data; } /** * Merges product information from cached et updates transients * to the main WordPress updates transients. * * @param array $update_transient The main WordPress themes or plugins updates transient. * @param array $et_update_products_data The cached et themes or plugins updates transient. * @return array */ function merge_et_products_response( $update_transient, $et_update_products_data ) { // If $et_update_products_data is empty or both its response and no_update arrays are empty, there is no cached data to merge and we can return the main WordPress transient. if ( empty( $et_update_products_data ) || ( empty( $et_update_products_data->response ) && empty( $et_update_products_data->no_update ) ) ) { return $update_transient; // Return the original transient if true. } // Fields to merge. $merge_data_fields = array( 'response', 'no_update', ); // Merge the fields. foreach ( $merge_data_fields as $data_field_name ) { if ( empty( $et_update_products_data->$data_field_name ) ) { continue; // Skip if the field is empty. } // Get the default response data. $default_response_data = ! empty( $update_transient->$data_field_name ) ? $update_transient->$data_field_name : array(); // Merge the data. $update_transient->$data_field_name = array_merge( $default_response_data, (array) $et_update_products_data->$data_field_name ); } // Check if the response array is empty in the cached transient, which is where products that need to be updated are listed. Before merging, we need to make sure the latest version isn't already installed, in which case it needs to be moved to the no_update array. if ( ! empty( $et_update_products_data->response ) ) { foreach ( $et_update_products_data->response as $product => $data ) { // Get the currently installed product version from the primary WordPress update transient. $installed_version = isset( $update_transient->checked[ $product ] ) ? $update_transient->checked[ $product ] : null; // Get the latest product version from the cached transient, handling both array and object cases. if ( is_array( $data ) ) { $latest_version = isset( $data['new_version'] ) ? $data['new_version'] : null; } elseif ( is_object( $data ) ) { $latest_version = isset( $data->new_version ) ? $data->new_version : null; } // If the currently installed version is the latest version, we need to move the product to the no_update array and remove the product from the response array. if ( $installed_version && $latest_version && version_compare( $installed_version, $latest_version, '>=' ) ) { $update_transient->no_update[ $product ] = $data; unset( $update_transient->response[ $product ] ); } } } // Now we need to do the opposite. Check if the no_update array is empty in the cached transient, which is where products that don't need to be updated are listed. If an update is required, move the product to the response array. if ( ! empty( $et_update_products_data->no_update ) ) { foreach ( $et_update_products_data->no_update as $product => $data ) { // Get the currently installed product version from the primary WordPress update transient. $installed_version = isset( $update_transient->checked[ $product ] ) ? $update_transient->checked[ $product ] : null; // Get the latest product version from the cached transient, handling both array and object cases. if ( is_array( $data ) ) { $latest_version = isset( $data['new_version'] ) ? $data['new_version'] : null; } elseif ( is_object( $data ) ) { $latest_version = isset( $data->new_version ) ? $data->new_version : null; } // If the currently installed version is not the latest version, we need to move the product to the response array and remove the product from the no_update array. if ( $installed_version && $latest_version && version_compare( $installed_version, $latest_version, '<' ) ) { $update_transient->response[ $product ] = $data; unset( $update_transient->no_update[ $product ] ); } } } return $update_transient; // Return the merged transient updated with the most recently cached product info. } function check_plugins_updates( $update_transient ) { global $wp_version; if ( ! isset( $update_transient->response ) ) { return $update_transient; } $plugins = []; $et_update_plugins = get_site_transient( 'et_update_plugins' ); // update_plugins transient gets set two times, so we ensure we make a request once if ( ! $this->upgraded_a_product && isset( $et_update_plugins->last_checked ) && isset( $update_transient->last_checked ) && $et_update_plugins->last_checked > ( $update_transient->last_checked - 10 * MINUTE_IN_SECONDS ) ) { return $this->merge_et_products_response( $update_transient, $et_update_plugins ); } $_plugins = get_plugins(); if ( empty( $_plugins ) ) { return $update_transient; } foreach ( $_plugins as $file => $plugin ) { $update_uri = isset( $plugin['UpdateURI'] ) ? $plugin['UpdateURI'] : ''; $is_et_uri = false !== strpos( $update_uri, 'elegantthemes.com' ); // Continue to the next iteration if the Update URI // is not empty and not using Elegant Themes's domain. if ( ! empty( $update_uri ) && ! $is_et_uri ) { continue; } $plugins[ $file ] = $plugin['Version']; } do_action( 'et_core_updates_before_request' ); $send_to_api = array( 'action' => 'check_all_plugins_updates', 'installed_plugins' => $plugins, 'class_version' => $this->version, ); // Add automatic updates data if Username and API key are set correctly $send_to_api = $this->maybe_add_automatic_updates_data( $send_to_api ); // If we don't have update values cached in the transient, we need to bypass rate limiting. if ( $et_update_plugins ) { $rate_limit = 'true'; } else { $rate_limit = 'false'; } $options = array( 'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 10 : 3), 'body' => $send_to_api, 'headers' => array( 'rate_limit' => $rate_limit, ), 'user-agent' => 'WordPress/' . $wp_version . '; Plugin Updates/' . ET_CORE_VERSION . '; ' . home_url( '/' ), ); $last_update = new stdClass(); $plugins_request = wp_remote_post( 'https://www.elegantthemes.com/api/api.php', $options ); $plugins_response = []; $et_update_plugins_updated = false; if ( ! is_wp_error( $plugins_request ) && wp_remote_retrieve_response_code( $plugins_request ) === 200 ){ $plugins_response = maybe_unserialize( wp_remote_retrieve_body( $plugins_request ) ); if ( ! empty( $plugins_response ) && is_array( $plugins_response ) ) { $et_update_plugins_updated = true; $request_settings = array( 'is_plugin_response' => true ); $plugins_response = $this->process_additional_response_settings( $plugins_response, $request_settings ); $last_update->checked = $plugins; $last_update->response = $plugins_response; $last_update = $this->add_up_to_date_products_data( $last_update, $request_settings ); $last_update->last_checked = time(); $update_transient = $this->merge_et_products_response( $update_transient, $plugins_response ); set_site_transient( 'et_update_plugins', $last_update ); $this->update_product_domains(); } } // if this is a rate limited or failed request, fallback to the last et_update_plugins value // rather than overwrite it with an empty response if ( ! $et_update_plugins_updated ) { $update_transient = $this->merge_et_products_response( $update_transient, $et_update_plugins ); } return $update_transient; } public function maybe_modify_plugins_changelog( $false, $action, $args ) { if ( 'plugin_information' !== $action ) { return $false; } if ( isset( $args->slug ) ) { $et_update_lb_plugin = get_site_transient( 'et_update_plugins' ); $plugin_basename = sprintf( '%1$s/%1$s.php', sanitize_text_field( $args->slug ) ); if ( isset( $et_update_lb_plugin->response[ $plugin_basename ] ) ) { $plugin_info = $et_update_lb_plugin->response[ $plugin_basename ]; if ( isset( $plugin_info->et_sections_used ) && 'on' === $plugin_info->et_sections_used ) { return $plugin_info; } } } return $false; } function process_account_settings( $response ) { if ( empty( $response['et_account_data'] ) ) { return $response; } $additional_settings_fields = array( 'et_username_status', 'et_api_key_status', 'et_expired_subscription', ); $et_account_data = $response['et_account_data']; $additional_settings = array(); $is_theme_response = is_array( $et_account_data ); foreach ( $additional_settings_fields as $additional_settings_field ) { $field = ''; $field_exists = $is_theme_response ? array_key_exists( $additional_settings_field, $et_account_data ) : ! empty( $et_account_data->$additional_settings_field ); if ( $field_exists ) { $field = $is_theme_response ? $et_account_data[ $additional_settings_field ] : $et_account_data->$additional_settings_field; } $additional_settings[ $additional_settings_field ] = $field; } if ( ! empty( $additional_settings[ 'et_username_status' ] ) && in_array( $additional_settings[ 'et_username_status' ], array( 'active', 'expired', 'not_found' ) ) ) { $this->account_status = sanitize_text_field( $additional_settings['et_username_status'] ); } else { // Set the account status to expired if the response array has 'et_expired_subscription' key $this->account_status = ! empty( $additional_settings[ 'et_expired_subscription' ] ) ? 'expired' : 'active'; } update_site_option( 'et_account_status', $this->account_status ); if ( ! empty( $additional_settings[ 'et_api_key_status' ] ) ) { update_site_option( 'et_account_api_key_status', sanitize_text_field( $additional_settings['et_api_key_status'] ) ); } else { delete_site_option( 'et_account_api_key_status' ); } unset( $response['et_account_data'] ); return $response; } function process_up_to_date_products_settings( $response, $settings ) { if ( empty( $response['et_up_to_date_products'] ) ) { return $response; } $products_category = $settings['is_plugin_response'] ? 'plugins' : 'themes'; $this->up_to_date_products_data[ $products_category ] = $response['et_up_to_date_products']; unset( $response['et_up_to_date_products'] ); return $response; } function process_request_settings( $settings = array() ) { $defaults = array( 'is_plugin_response' => false, ); return array_merge( $defaults, $settings ); } function process_additional_response_settings( $response, $settings = array() ) { if ( empty( $response ) ) { return $response; } $settings = $this->process_request_settings( $settings ); $response = $this->process_account_settings( $response ); $response = $this->process_up_to_date_products_settings( $response, $settings ); return $response; } /** * Sends a request to server, gets current themes versions * * @param object $update_transient Update transient option * @return object Update transient option */ function check_themes_updates( $update_transient ){ global $wp_version; $et_update_themes = get_site_transient( 'et_update_themes' ); // update_themes transient gets set two times, so we ensure we make a request once if ( ! $this->upgraded_a_product && isset( $et_update_themes->last_checked ) && isset( $update_transient->last_checked ) && $et_update_themes->last_checked > ( $update_transient->last_checked - 10 * MINUTE_IN_SECONDS ) ) { return $this->merge_et_products_response( $update_transient, $et_update_themes ); } if ( ! isset( $update_transient->checked ) ) { return $update_transient; } $themes = $update_transient->checked; do_action( 'et_core_updates_before_request' ); $send_to_api = array( 'action' => 'check_theme_updates', 'installed_themes' => $themes, 'class_version' => $this->version, ); // Add automatic updates data if Username and API key are set correctly $send_to_api = $this->maybe_add_automatic_updates_data( $send_to_api ); // If we don't have update values cached in the transient, we need to bypass rate limiting. if ( $et_update_themes ) { $rate_limit = 'true'; } else { $rate_limit = 'false'; } $options = array( 'timeout' => ( ( defined('DOING_CRON') && DOING_CRON ) ? 10 : 3 ), 'body' => $send_to_api, 'headers' => array( 'rate_limit' => $rate_limit, ), 'user-agent' => 'WordPress/' . $wp_version . '; Theme Updates/' . ET_CORE_VERSION . '; ' . home_url( '/' ), ); $last_update = new stdClass(); $theme_request = wp_remote_post( 'https://www.elegantthemes.com/api/api.php', $options ); $theme_response = []; $et_update_themes_updated = false; if ( ! is_wp_error( $theme_request ) && wp_remote_retrieve_response_code( $theme_request ) === 200 ){ $theme_response = maybe_unserialize( wp_remote_retrieve_body( $theme_request ) ); if ( ! empty( $theme_response ) && is_array( $theme_response ) ) { $et_update_themes_updated = true; $theme_response = $this->process_additional_response_settings( $theme_response ); $last_update->checked = $themes; $last_update->response = $theme_response; $last_update = $this->add_up_to_date_products_data( $last_update ); $last_update->last_checked = time(); $update_transient = $this->merge_et_products_response( $update_transient, $last_update ); set_site_transient( 'et_update_themes', $last_update ); $this->update_product_domains(); } } // if this is a rate limited or failed request, fallback to the last et_update_themes value // rather than overwrite it with an empty response if ( ! $et_update_themes_updated ) { $update_transient = $this->merge_et_products_response( $update_transient, $et_update_themes ); } return $update_transient; } function maybe_show_account_notice() { // Don't show notice on onboarding page. if ( isset( $_GET['page'] ) && 'et_onboarding' === $_GET['page'] ) { return; } if ( empty( $this->options['username'] ) || empty( $this->options['api_key'] ) ) { return; } $all_products = $this->get_et_api_products(); $total_products = count( $all_products['theme'] ) + count( $all_products['plugin'] ); if ( 1 === $total_products && et_()->includes( $all_products['plugin'], 'Divi Dash' ) ) { // Don't show the notice when Divi Dash is the only product return; } $output = ''; $messages = array(); $account_api_key_status = get_site_option( 'et_account_api_key_status' ); $is_expired_account = 'expired' === $this->account_status; $is_invalid_account = 'not_found' === $this->account_status; if ( ! $is_expired_account && ! $is_invalid_account && empty( $account_api_key_status ) ) { return; } if ( $is_expired_account ) { $messages[] = et_get_safe_localization( __( 'Your Elegant Themes subscription has expired. You must renew your account to regain access to product updates and support. To ensure compatibility and security, it is important to always keep your themes and plugins updated.', 'et-core' ) ); } else if ( $is_invalid_account ) { $messages[] = et_get_safe_localization( __( 'The Elegant Themes username you entered is invalid. Please enter a valid username to receive product updates. If you forgot your username you can request it here.', 'et-core' ) ); } if ( ! empty( $account_api_key_status ) ) { switch ( $account_api_key_status ) { case 'deactivated': $status = 'not active'; break; default: $status = 'invalid'; break; } $messages[] = et_get_safe_localization( __( sprintf( 'The Elegant Themes API key you entered is %1$s. Please make sure that your API has been entered correctly and that it is enabled in your account.', $status ), 'et-core' ) ); } foreach ( $messages as $message ) { $output .= sprintf( '

    %1$s

    ', $message ); } if ( empty( $output ) ) { return; } $dashboard_url = add_query_arg( 'et_action', 'update_account_details', admin_url( 'update-core.php' ) ); printf( '
    %1$s

    %3$s

    ', $output, esc_url( wp_nonce_url( $dashboard_url, 'et_update_account_details', 'et_update_account_details_nonce' ) ), esc_html__( 'Check Again', 'et-core' ) ); } function change_plugin_changelog_url( $url, $path ) { if ( 0 !== strpos( $path, 'plugin-install.php?tab=plugin-information&plugin=' ) ) { return $url; } $matches = array(); $update_transient = get_site_transient( 'et_update_plugins' ); $et_updated_plugins_data = get_transient( 'et_updated_plugins_data' ); $has_last_checked = ! empty( $update_transient->last_checked ) && ! empty( $et_updated_plugins_data->last_checked ); if ( ! is_object( $update_transient ) ) { return $url; } /* * Attempt to use a cached list of updated plugins. * Re-save the list, whenever the update transient last checked time changes. */ if ( false === $et_updated_plugins_data || ( $has_last_checked && $update_transient->last_checked !== $et_updated_plugins_data->last_checked ) ) { $et_updated_plugins_data = new stdClass(); if ( ! empty( $update_transient->last_checked ) ) { $et_updated_plugins_data->last_checked = $update_transient->last_checked; } foreach ( $update_transient->response as $response_plugin_settings ) { $slug = sanitize_text_field( $response_plugin_settings->slug ); $et_updated_plugins_data->changelogs[ $slug ] = esc_url_raw( $response_plugin_settings->url . '?TB_iframe=true&width=1024&height=800' ); } set_transient( 'et_updated_plugins_data', $et_updated_plugins_data ); } if ( ! empty( $update_transient->no_update ) ) { foreach ( $update_transient->no_update as $no_update_plugin_settings ) { $slug = sanitize_text_field( $no_update_plugin_settings->slug ); $et_updated_plugins_data->changelogs[ $slug ] = esc_url_raw( $no_update_plugin_settings->url . '?TB_iframe=true&width=1024&height=800' ); } } preg_match( '/plugin=([^&]*)/', $path, $matches ); $current_plugin_slug = $matches[1]; // Check if we're dealing with a product that has a custom changelog URL if ( ! empty( $et_updated_plugins_data->changelogs[ $current_plugin_slug ] ) ) { $url = esc_url_raw( $et_updated_plugins_data->changelogs[ $current_plugin_slug ] ); } return $url; } function force_update_requests() { $update_transients = array( 'update_themes', 'update_plugins', 'et_update_themes', 'et_update_plugins', ); foreach ( $update_transients as $update_transient ) { if ( get_site_transient( $update_transient ) ) { delete_site_transient( $update_transient ); } } } function update_product_domains() { $this->all_et_products_domains = $this->get_all_et_products(); $append_notification_action_name = 'maybe_append_custom_notification'; // update notifications for ET products if needed foreach ( array( 'theme', 'plugin' ) as $product_type ) { if ( empty( $this->all_et_products_domains[ $product_type] ) ) { continue; } foreach ( $this->all_et_products_domains[ $product_type ] as $product_key ) { $action_name = sanitize_text_field( sprintf( 'in_%1$s_update_message-%2$s', $product_type, $product_key ) ); if ( has_action( $action_name, array( $this, $append_notification_action_name ) ) ) { continue; } add_action( $action_name, array( $this, $append_notification_action_name ), 10, 2 ); } } } /** * Delete Elegant Themes update products transient, whenever default WordPress update transient gets removed */ function maybe_reset_et_products_update_transient( $transient_name ) { // Transient names for update transients we're interested in. $update_transients_names = array( 'update_themes' => 'et_update_themes', 'update_plugins' => 'et_update_plugins', ); // Check if the transient name is one of the update transients we're interested in. if ( empty( $update_transients_names[ $transient_name ] ) ) { return; } // Check the last_checked time in the transient, and only delete it if it's older than 24 hours. $et_update_transient = get_site_transient( $update_transients_names[ $transient_name ] ); if ( ! empty( $et_update_transient->last_checked ) && $et_update_transient->last_checked > ( time() - DAY_IN_SECONDS ) ) { return; } // Delete the ET update transient, because it's older than 24 hours. delete_site_transient( $update_transients_names[ $transient_name ] ); } /** * Detects if the current API request is related to a product update. * In this case, we need to allow the request to bypass rate limiting * since the update process requests two requests. */ function upgraded_a_product() { $this->upgraded_a_product = true; } } endif; if ( ! function_exists( 'et_core_enable_automatic_updates' ) ) : function et_core_enable_automatic_updates( $deprecated, $version ) { if ( ! is_admin() && ! wp_doing_cron() ) { return; } if ( isset( $GLOBALS['et_core_updates'] ) ) { return; } if ( defined( 'ET_CORE_URL' ) ) { $url = ET_CORE_URL; } else { $url = trailingslashit( $deprecated ) . 'core/'; } $GLOBALS['et_core_updates'] = new ET_Core_Updates( $url, $version ); } endif; PKE\Z""components/Cache.phpnu[owner = self::_validate_property( 'owner', $owner ); $this->post_id = self::_validate_property( 'post_id', $post_id ? $post_id : et_core_page_resource_get_the_ID() ); $this->type = self::_validate_property( 'type', $type ); $this->location = self::_validate_property( 'location', $location ); $this->write_file_location = $this->location; $this->filename = sanitize_file_name( "et-{$this->owner}-{$slug}-{$post_id}" ); $this->slug = "{$this->filename}-cached-inline-{$this->type}s"; $this->data = array(); $this->priority = $priority; self::startup(); $this->_initialize_resource(); } /** * Activates the class */ public static function startup() { if ( null !== self::$_resources ) { // Class has already been initialized return; } $time = (string) microtime( true ); $time = str_replace( '.', '', $time ); $rand = (string) mt_rand(); self::$_request_time = $time; self::$_request_id = "{$time}-{$rand}"; self::$_resources = array(); self::$data_utils = new ET_Core_Data_Utils(); foreach ( self::$_output_locations as $location ) { self::$_resources_by_location[ $location ] = array(); } foreach ( self::$_scopes as $scope ) { self::$_resources_by_scope[ $scope ] = array(); } // phpcs:enable self::$WP_CONTENT_DIR = self::$data_utils->normalize_path( WP_CONTENT_DIR ); self::$_lock_file = self::$_request_id . '~'; self::_register_callbacks(); self::_setup_wp_filesystem(); self::$_can_write = et_core_cache_dir()->can_write; } /** * Cleanup and save */ public static function shutdown() { if ( ! self::$_resources || ! self::$_can_write ) { return; } // Remove any leftover temporary directories that belong to this request foreach ( self::$_temp_dirs as $temp_directory ) { if ( file_exists( $temp_directory . '/' . self::$_lock_file ) ) { @self::$wpfs->delete( $temp_directory, true ); } } // Reset $_resources property; Mostly useful for unit test big request which needs to make // each test*() method act like it is different page request self::$_resources = null; if ( et_()->WPFS()->exists( self::$WP_CONTENT_DIR . '/cache/et' ) ) { // Remove old cache directory et_()->WPFS()->rmdir( self::$WP_CONTENT_DIR . '/cache/et', true ); } } protected static function _assign_output_location( $location, $resource ) { $priority_existed = isset( self::$_resources_by_location[ $location ][ $resource->priority ] ); self::$_resources_by_location[ $location ][ $resource->priority ][ $resource->slug ] = $resource; if ( ! $priority_existed ) { // We've added a new priority to the list, so put them back in sorted order. ksort( self::$_resources_by_location[ $location ], SORT_NUMERIC ); } } /** * Enqueues static file for provided script resource. * * @param ET_Core_PageResource $resource page resources. */ protected static function _enqueue_script( $resource ) { // Bust PHP's stats cache for the resource file to ensure we get the latest timestamp. clearstatcache( true, $resource->path ); $can_enqueue = 0 === did_action( 'wp_print_scripts' ); $timestamp = filemtime( $resource->path ); if ( $can_enqueue ) { wp_enqueue_script( $resource->slug, set_url_scheme( $resource->url ), array(), $timestamp, true ); } else { $timestamp = $timestamp ? $timestamp : ET_CORE_VERSION; printf( '', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript esc_attr( $resource->slug ), esc_url( set_url_scheme( $resource->url . "?ver={$timestamp}" ) ) ); } $resource->enqueued = true; } /** * Enqueues static file for provided style resource. * * @param ET_Core_PageResource $resource */ protected static function _enqueue_style( $resource ) { if ( 'footer' === self::$current_output_location ) { return; } // Bust PHP's stats cache for the resource file to ensure we get the latest timestamp. clearstatcache( true, $resource->path ); $can_enqueue = 0 === did_action( 'wp_print_scripts' ); // reason: We do this on purpose when a style can't be enqueued. // phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet $template = ''; // phpcs:enable $timestamp = filemtime( $resource->path ); if ( $can_enqueue ) { wp_enqueue_style( $resource->slug, set_url_scheme( $resource->url ), array(), $timestamp ); } else { // reason: this whole file needs to be converted. // phpcs:disable ET.Sniffs.ValidVariableName.UsedPropertyNotSnakeCase $timestamp = $timestamp ?: ET_CORE_VERSION; $slug = esc_attr( $resource->slug ); $scheme = esc_url( set_url_scheme( $resource->url . "?ver={$timestamp}" ) ); $tag = sprintf( $template, $slug, $scheme ); $onload = et_core_esc_previously( self::$_onload ); // phpcs:enable $tag = apply_filters( 'et_core_page_resource_tag', $tag, $slug, $scheme, $onload ); print( et_core_esc_previously( $tag ) ); } $resource->enqueued = true; } /** * Returns the next output location. * * @see self::$_output_locations * * @return string */ protected static function _get_next_output_location() { $current_index = array_search( self::$current_output_location, self::$_output_locations, true ); if ( false === $current_index || ! is_int( $current_index ) ) { ET_Core_Logger::error( '$current_output_location is invalid!' ); } $current_index += 1; return self::$_output_locations[ $current_index ]; } /** * Creates static resource files for an output location if needed. * * @param string $location {@link self::$_output_locations}. */ protected static function _maybe_create_static_resources( $location ) { self::$current_output_location = $location; // Disable for footer inside builder if page uses Theme Builder Editor to avoid conflict with critical CSS. if ( 'footer' === $location && et_core_is_fb_enabled() && et_fb_is_theme_builder_used_on_page() ) { return false; } $sorted_resources = self::get_resources_by_output_location( $location ); foreach ( $sorted_resources as $priority => $resources ) { foreach ( $resources as $slug => $resource ) { if ( $resource->write_file_location !== $location ) { // This resource's static file needs to be generated later on. self::_assign_output_location( $resource->write_file_location, $resource ); continue; } if ( ! self::$_can_write ) { // The reason we don't simply check this before looping through resources and // bail if it fails is because we need to perform the output location assignment // in the previous conditional regardless (otherwise builder styles will break). continue; } if ( $resource->forced_inline || $resource->has_file() ) { continue; } $data = $resource->get_data( 'file' ); if ( empty( $data ) && 'footer' !== $location ) { // This resource doesn't have any data yet so we'll assign it to the next output location. $next_location = self::_get_next_output_location(); $resource->set_output_location( $next_location ); continue; } $force_write = apply_filters( 'et_core_page_resource_force_write', false, $resource ); if ( ! $force_write && empty( $data ) ) { continue; } // Make sure directory exists. if ( ! self::$data_utils->ensure_directory_exists( $resource->base_dir ) ) { self::$_can_write = false; return; } $can_continue = true; // Try to create a temporary directory which we'll use as a pseudo file lock if ( @mkdir( $resource->temp_dir, 0755 ) ) { //phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- Just ignore this since it's an internal use. self::$_temp_dirs[] = $resource->temp_dir; // Make sure another request doesn't delete our temp directory. $lock_file = $resource->temp_dir . '/' . self::$_lock_file; self::$wpfs->put_contents( $lock_file, '' ); // Create the static resource file if ( ! self::$wpfs->put_contents( $resource->path, $data, 0644 ) ) { // There's no point in continuing self::$_can_write = $can_continue = false; } else { // Remove the temporary directory self::$wpfs->delete( $resource->temp_dir, true ); /** * Fires when the static resource file is created. * * @since 4.10.8 * * @param object $resource The resource object. */ do_action( 'et_core_static_file_created', $resource ); } } elseif ( file_exists( $resource->temp_dir ) ) { // The static resource file is currently being created by another request continue; } else { // Failed for some other reason. There's no point in continuing self::$_can_write = $can_continue = false; return; } if ( ! $can_continue ) { return; } if ( ! defined( 'DONOTCACHEPAGE' ) ) { define( 'DONOTCACHEPAGE', true ); } } } } /** * Enqueues static files for an output location if available. * * @param string $location {@link self::$_output_locations}. */ protected static function _maybe_enqueue_static_resources( $location ) { $sorted_resources = self::get_resources_by_output_location( $location ); foreach ( $sorted_resources as $priority => $resources ) { foreach ( $resources as $slug => $resource ) { if ( $resource->disabled ) { // Resource is disabled. Remove it from the queue. self::_unassign_output_location( $location, $resource ); continue; } if ( $resource->forced_inline || ! $resource->url || ! $resource->has_file() ) { continue; } if ( 'style' === $resource->type ) { self::_enqueue_style( $resource ); } elseif ( 'script' === $resource->type ) { self::_enqueue_script( $resource ); } if ( $resource->enqueued ) { self::_unassign_output_location( $location, $resource ); } } } } /** * Outputs all non-enqueued resources for an output location inline. * * @param string $location {@link self::$_output_locations}. */ protected static function _maybe_output_inline_resources( $location ) { $sorted_resources = self::get_resources_by_output_location( $location ); foreach ( $sorted_resources as $priority => $resources ) { foreach ( $resources as $slug => $resource ) { if ( $resource->disabled ) { // Resource is disabled. Remove it from the queue. self::_unassign_output_location( $location, $resource ); continue; } $data = $resource->get_data( 'inline' ); $same_write_file_location = $resource->write_file_location === $resource->location; if ( empty( $data ) && 'footer' !== $location && $same_write_file_location ) { // This resource doesn't have any data yet so we'll assign it to the next output location. $next_location = self::_get_next_output_location(); $resource->set_output_location( $next_location ); continue; } elseif ( empty( $data ) ) { continue; } printf( '<%1$s id="%2$s">%3$s', esc_html( $resource->type ), esc_attr( $resource->slug ), et_core_esc_previously( wp_strip_all_tags( $data ) ) ); if ( $same_write_file_location ) { // File wasn't created during this location's callback and it won't be created later $resource->inlined = true; } } } } /** * Registers necessary callbacks. */ protected static function _register_callbacks() { $class = 'ET_Core_PageResource'; // Output Location: head-early, right after theme styles have been enqueued. add_action( 'wp_enqueue_scripts', array( $class, 'head_early_output_cb' ), 11 ); // Output Location: head, right BEFORE the theme and wp's custom css. add_action( 'wp_head', array( $class, 'head_output_cb' ), 99 ); // Output Location: head-late, right AFTER the theme and wp's custom css. add_action( 'wp_head', array( $class, 'head_late_output_cb' ), 103 ); // Output Location: footer. add_action( 'wp_footer', array( $class, 'footer_output_cb' ), 20 ); // Always delete cached resources for a post upon saving. add_action( 'save_post', array( $class, 'save_post_cb' ), 10, 3 ); // Always delete cached resources for theme customizer upon saving. add_action( 'customize_save_after', array( $class, 'customize_save_after_cb' ) ); /* * Always delete dynamic css when saving widgets. * `widget_update_callback` fires on save for any of the present widgets, * `delete_widget` fires on save for any deleted widget. */ add_filter( 'widget_update_callback', array( $class, 'widget_update_callback_cb' ) ); add_filter( 'delete_widget', array( $class, 'widget_update_callback_cb' ) ); } /** * Initializes the WPFilesystem class. */ protected static function _setup_wp_filesystem() { // The wpfs instance will always exists at this point because the cache dir class initializes it beforehand self::$wpfs = $GLOBALS['wp_filesystem']; } /** * Unassign a resource from an output location. * * @param string $location {@link self::$_output_locations}. * @param ET_Core_PageResource $resource */ protected static function _unassign_output_location( $location, $resource ) { unset( self::$_resources_by_location[ $location ][ $resource->priority ][ $resource->slug ] ); } protected static function _validate_property( $property, $value ) { $valid_values = array( 'location' => self::$_output_locations, 'owner' => self::$_owners, 'type' => self::$_types, ); switch ( $property ) { case 'path': $value = et_()->normalize_path( realpath( $value ) ); $is_valid = et_()->starts_with( $value, et_core_cache_dir()->path ); break; case 'url': $base_url = et_core_cache_dir()->url; $is_valid = et_()->starts_with( $value, set_url_scheme( $base_url, 'http' ) ); $is_valid = $is_valid ? $is_valid : et_()->starts_with( $value, set_url_scheme( $base_url, 'https' ) ); break; case 'post_id': $is_valid = 'global' === $value || 'all' === $value || is_numeric( $value ); break; default: $is_valid = isset( $valid_values[ $property ] ) && in_array( $value, $valid_values[ $property ] ); break; } return $is_valid ? $value : ''; } /** * Whether or not we are able to write to the filesystem. * * @return bool */ public static function can_write_to_filesystem() { return ET_Core_Cache_Directory::instance()->can_write; } /** * Output Location: footer * {@see 'wp_footer' (20) Allow third-party extensions some room to do what they do} */ public static function footer_output_cb() { self::_maybe_create_static_resources( 'footer' ); self::_maybe_enqueue_static_resources( 'footer' ); self::_maybe_output_inline_resources( 'footer' ); } /** * Returns the absolute path to our cache directory. * * @since 4.0.8 Removed `$path_type` param b/c cache directory might not be located under wp-content. * @since 3.0.52 * * @return string */ public static function get_cache_directory() { return et_core_cache_dir()->path; } /** * Returns all current resources. * * @return array {@link self::$_resources} */ public static function get_resources() { return self::$_resources; } /** * Returns the current resources for the provided output location, sorted by priority. * * @param string $location The desired output location {@see self::$_output_locations}. * * @return array[] { * * @type ET_Core_PageResource[] $priority { * * @type ET_Core_PageResource $slug Resource. * ... * } * ... * } */ public static function get_resources_by_output_location( $location ) { return self::$_resources_by_location[ $location ]; } /** * Returns the current resources for the provided scope. * * @param string $scope The desired scope (post|global). * * @return ET_Core_PageResource[] */ public static function get_resources_by_scope( $scope ) { return self::$_resources_by_scope[ $scope ]; } /** * Output Location: head-early * {@see 'wp_enqueue_scripts' (11) Should run right after the theme enqueues its styles.} */ public static function head_early_output_cb() { self::_maybe_create_static_resources( 'head-early' ); self::_maybe_enqueue_static_resources( 'head-early' ); self::_maybe_output_inline_resources( 'head-early' ); } /** * Output Location: head * {@see 'wp_head' (99) Must run BEFORE the theme and WP's custom css callbacks.} */ public static function head_output_cb() { self::_maybe_create_static_resources( 'head' ); self::_maybe_enqueue_static_resources( 'head' ); self::_maybe_output_inline_resources( 'head' ); } /** * Output Location: head-late * {@see 'wp_head' (103) Must run AFTER the theme and WP's custom css callbacks.} */ public static function head_late_output_cb() { self::_maybe_create_static_resources( 'head-late' ); self::_maybe_enqueue_static_resources( 'head-late' ); self::_maybe_output_inline_resources( 'head-late' ); } /** * {@see 'widget_update_callback'} * * @param array $instance Widget settings being saved. */ public static function widget_update_callback_cb( $instance ) { self::remove_static_resources( 'all', 'all', false, 'dynamic' ); return $instance; } /** * {@see 'customize_save_after'} * * @param WP_Customize_Manager $manager */ public static function customize_save_after_cb( $manager ) { self::remove_static_resources( 'all', 'all' ); } /** * {@see 'save_post'} * * @param int $post_id * @param WP_Post $post * @param bool $update */ public static function save_post_cb( $post_id, $post, $update ) { // In Dynamic CSS, we parse the layout content for generating styles and store it under the `object_id`, so clearing // only the layout assets won't update the page style if we made any changes to the layout/global modules etc. // Hence, we need to clear all static resources when we update a layout. // Also, we should only clear the cache if the layout being saved is a global module/row/section. if ( 'et_pb_layout' === $post->post_type ) { $taxonomies = get_taxonomies( [ 'object_type' => [ 'et_pb_layout' ] ] ); $tax_to_clear = array( 'scope', 'layout_type' ); $types_to_clear = array( 'module', 'row', 'section' ); $scope_terms = get_the_terms( $post_id, 'scope' ); $layout_terms = get_the_terms( $post_id, 'layout_type' ); if ( ! empty( $scope_terms ) && ! empty( $layout_terms ) ) { $scope_terms = wp_list_pluck( $scope_terms, 'slug' ); $layout_terms = wp_list_pluck( $layout_terms, 'slug' ); $is_global = in_array( 'global', $scope_terms, true ); $clearable_modules = array_intersect( $types_to_clear, $layout_terms ); $remove_resource = $is_global && ! empty( $clearable_modules ); foreach ( $taxonomies as $taxonomy ) { if ( in_array( $taxonomy, $tax_to_clear, true ) && $remove_resource ) { $post_id = 'all'; break; } } } } self::remove_static_resources( $post_id, 'all' ); } /** * Remove static resources for a post, or optionally all resources, if any exist. * * @param string $post_id id of post. * @param string $owner owner of file. * @param bool $force remove all resources. * @param string $slug file slug. */ public static function remove_static_resources( $post_id, $owner = 'core', $force = false, $slug = 'all' ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( ! wp_doing_cron() && ! et_core_security_check_passed( 'edit_posts' ) ) { return; } if ( ! self::can_write_to_filesystem() ) { return; } if ( ! self::$data_utils ) { self::startup(); } self::do_remove_static_resources( $post_id, $owner, $force, $slug ); } /** * Remove static resources action. * * @param string $post_id id of post. * @param string $owner owner of file. * @param bool $force remove all resources. * @param string $slug file slug. */ public static function do_remove_static_resources( $post_id, $owner = 'core', $force = false, $slug = 'all' ) { $post_id = self::_validate_property( 'post_id', $post_id ); $owner = self::_validate_property( 'owner', $owner ); $slug = sanitize_key( $slug ); if ( '' === $owner || '' === $post_id ) { return; } $_post_id = 'all' === $post_id ? '*' : $post_id; $_owner = 'all' === $owner ? '*' : $owner; $_slug = 'all' === $slug ? '*' : $slug; $cache_dir = self::get_cache_directory(); $files = array_merge( // Remove any CSS files missing a parent folder. (array) glob( "{$cache_dir}/et-{$_owner}-*" ), // Remove CSS files for individual posts or all posts if $post_id set to 'all'. (array) glob( "{$cache_dir}/{$_post_id}/et-{$_owner}-{$_slug}*" ), // Remove CSS files that contain theme builder template CSS. // Multiple directories need to be searched through since * doesn't match / in the glob pattern. (array) glob( "{$cache_dir}/*/et-{$_owner}-{$_slug}-*tb-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/*/et-{$_owner}-{$_slug}-*tb-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/*/*/et-{$_owner}-{$_slug}-*tb-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/et-{$_owner}-{$_slug}-*tb-for-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/*/et-{$_owner}-{$_slug}-*tb-for-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/*/*/et-{$_owner}-{$_slug}-*tb-for-{$_post_id}*" ), // Remove Dynamic CSS files for categories, tags, authors, archives, homepage post feed and search results. (array) glob( "{$cache_dir}/taxonomy/*/*/et-{$_owner}-dynamic*" ), (array) glob( "{$cache_dir}/author/*/et-{$_owner}-dynamic*" ), (array) glob( "{$cache_dir}/archive/et-{$_owner}-dynamic*" ), (array) glob( "{$cache_dir}/search/et-{$_owner}-dynamic*" ), (array) glob( "{$cache_dir}/notfound/et-{$_owner}-dynamic*" ), (array) glob( "{$cache_dir}/home/et-{$_owner}-dynamic*" ), // WP Templates and Template Parts. (array) glob( "{$cache_dir}/*/et-{$_owner}-{$_slug}-*wpe-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/*/et-{$_owner}-{$_slug}-*wpe-{$_post_id}*" ), (array) glob( "{$cache_dir}/*/*/*/et-{$_owner}-{$_slug}-*wpe-{$_post_id}*" ) ); self::_remove_files_in_directory( $files, $cache_dir ); // Remove empty directories. self::$data_utils->remove_empty_directories( $cache_dir ); // Clear cache managed by 3rd-party cache plugins. $post_id = ! empty( $post_id ) && absint( $post_id ) > 0 ? $post_id : ''; et_core_clear_wp_cache( $post_id ); // Purge the module features cache. if ( class_exists( 'ET_Builder_Module_Features' ) ) { if ( ! empty( $post_id ) ) { ET_Builder_Module_Features::purge_cache( $post_id ); } else { ET_Builder_Module_Features::purge_cache(); } } // Purge the google fonts cache. if ( empty( $post_id ) && class_exists( 'ET_Builder_Google_Fonts_Feature' ) ) { ET_Builder_Google_Fonts_Feature::purge_cache(); } // Purge the dynamic assets cache. if ( empty( $post_id ) && class_exists( 'ET_Builder_Dynamic_Assets_Feature' ) ) { ET_Builder_Dynamic_Assets_Feature::purge_cache(); } $post_meta_caches = array( 'et_enqueued_post_fonts', '_et_dynamic_cached_shortcodes', '_et_dynamic_cached_attributes', '_et_builder_module_features_cache', ); // Clear post meta caches. foreach ( $post_meta_caches as $post_meta_cache ) { if ( ! empty( $post_id ) ) { delete_post_meta( $post_id, $post_meta_cache ); } else { delete_post_meta_by_key( $post_meta_cache ); } } // Set our DONOTCACHEPAGE file for the next request. self::$data_utils->ensure_directory_exists( $cache_dir ); self::$wpfs->put_contents( $cache_dir . '/DONOTCACHEPAGE', '' ); if ( $force ) { delete_option( 'et_core_page_resource_remove_all' ); } /** * Fires when the static resources are removed. * * @since 4.21.1 * * @param mixed $post_id The post ID. */ do_action( 'et_core_static_resources_removed', $post_id ); } /** * Removes a list of files from the designated directory. * * @param array[] $files List of patterns to match. * @param string $cache_dir Cache directory. */ protected static function _remove_files_in_directory( $files, $cache_dir ) { foreach ( $files as $file ) { $file = self::$data_utils->normalize_path( $file ); if ( ! et_()->starts_with( $file, $cache_dir ) ) { // File is not located inside cache directory so skip it. continue; } if ( is_file( $file ) ) { self::$wpfs->delete( $file ); } } } public static function wpfs() { if ( null !== self::$wpfs ) { return self::$wpfs; } self::startup(); return self::$wpfs = et_core_cache_dir()->wpfs; } protected function _initialize_resource() { if ( ! self::can_write_to_filesystem() ) { $this->base_dir = $this->temp_dir = $this->path = $this->url = ''; //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found -- Just ignore this since it's an internal use. $this->_register_resource(); return; } $file_extension = 'style' === $this->type ? '.min.css' : '.min.js'; $path = self::get_cache_directory(); $url = et_core_cache_dir()->url; $file = et_()->path( $path, $this->post_id, $this->filename . $file_extension ); if ( file_exists( $file ) ) { // Static resource file exists $this->path = self::$data_utils->normalize_path( $file ); $this->base_dir = dirname( $this->path ); $this->url = et_()->path( $url, $this->post_id, basename( $this->path ) ); } else { // Static resource file doesn't exist $url .= "/{$this->post_id}/{$this->filename}{$file_extension}"; $path .= "/{$this->post_id}/{$this->filename}{$file_extension}"; $this->base_dir = self::$data_utils->normalize_path( dirname( $path ) ); $this->temp_dir = $this->base_dir . "/{$this->slug}~"; $this->path = $path; $this->url = $url; } $this->_register_resource(); } protected function _register_resource() { $this->enqueued = false; $this->inlined = false; $scope = 'global' === $this->post_id ? 'global' : 'post'; self::$_resources[ $this->slug ] = $this; self::$_resources_by_scope[ $scope ][ $this->slug ] = $this; self::_assign_output_location( $this->location, $this ); } public function get_data( $context ) { $result = ''; ksort( $this->data, SORT_NUMERIC ); /** * Filters the resource's data array. * * @since 3.0.52 * * @param array[] $data { * * @type string[] $priority Resource data. * ... * } * @param string $context Where the data will be used. Accepts 'inline', 'file'. * @param ET_Core_PageResource $resource The resource instance. */ $resource_data = apply_filters( 'et_core_page_resource_get_data', $this->data, $context, $this ); foreach ( $resource_data as $priority => $data_part ) { foreach ( $data_part as $data ) { $result .= $data; } } return $result; } /** * Whether or not a static resource exists on the filesystem for this instance. * * @return bool */ public function has_file() { if ( ! self::$wpfs || empty( $this->path ) || ! self::can_write_to_filesystem() ) { return false; } return self::$wpfs->exists( $this->path ); } /** * Set the resource's data. * * @param string $data * @param int $priority */ public function set_data( $data, $priority = 10 ) { if ( 'style' === $this->type ) { $data = et_core_data_utils_minify_css( $data ); // Remove empty media queries // @media only..and (feature:value) { } $pattern = '/@media\s+([\w\s]+)?\([\w-]+:[\w\d-]+\)\{\s*\}/'; $data = preg_replace( $pattern, '', $data ); } $this->data[ $priority ][] = trim( strip_tags( str_replace( '\n', '', $data ) ) ); } public function set_output_location( $location ) { if ( ! self::_validate_property( 'location', $location ) ) { return; } $current_location = $this->location; self::_unassign_output_location( $current_location, $this ); self::_assign_output_location( $location, $this ); $this->location = $location; } public function unregister_resource() { $scope = 'global' === $this->post_id ? 'global' : 'post'; unset( self::$_resources[ $this->slug ], self::$_resources_by_scope[ $scope ][ $this->slug ] ); self::_unassign_output_location( $this->location, $this ); } } PKE\K\components/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\K`components/Logger.phpnu[ 0 && ! isset( $backtrace[ $bt_index ] ) ) { $bt_index--; } // We need two stacks to get all the data we need so let's go down one more $bt_index--; } $stack = $backtrace[ $bt_index ]; $file = self::$_->array_get( $stack, 'file', '' ); $line = self::$_->array_get( $stack, 'line', '' ); // Name of the function and class (if applicable) are in the previous stack (stacks are in reverse order) $stack = $backtrace[ $bt_index + 1 ]; $class = self::$_->array_get( $stack, 'class', '' ); $function = self::$_->array_get( $stack, 'function', '' ); if ( $class ) { $class .= '::'; } if ( '' !== $file ) { $file = _et_core_normalize_path( $file ); $parts = explode( '/', $file ); $parts = array_slice( $parts, -2 ); $file = ".../{$parts[0]}/{$parts[1]}"; } $message = " {$file}:{$line} {$class}{$function}():\n{$message}\n"; error_log( $message ); } /** * Writes message to the logs if {@link WP_DEBUG} is `true`, otherwise does nothing. * * @since 1.1.0 * * @param mixed $message * @param int $bt_index * @param boolean $log_ajax Whether or not to log on AJAX calls. */ public static function debug( $message, $bt_index = 4, $log_ajax = true ) { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { self::_maybe_write_log( $message, $bt_index, $log_ajax ); } } public static function disable_php_notices() { $error_reporting = error_reporting(); $notices_enabled = $error_reporting & E_NOTICE; if ( $notices_enabled ) { error_reporting( $error_reporting & ~E_NOTICE ); } } /** * Writes an error message to the logs regardless of whether or not debug mode is enabled. * * @since 1.1.0 * * @param mixed $message * @param int $bt_index */ public static function error( $message, $bt_index = 4 ) { self::_maybe_write_log( $message, $bt_index ); } public static function enable_php_notices() { $error_reporting = error_reporting(); $notices_enabled = $error_reporting & E_NOTICE; if ( ! $notices_enabled ) { error_reporting( $error_reporting | E_NOTICE ); } } public static function initialize() { self::$_ = ET_Core_Data_Utils::instance(); } public static function php_notices_enabled() { $error_reporting = error_reporting(); return $error_reporting & E_NOTICE; } } ET_Core_Logger::initialize(); PKE\oL`components/README.mdnu[## Core Components This directory contains all of Core's PHP Components. Components are organized into groups using a nested directory structure. ### What's Inside |File|Name|Description| |:--------|:----------|:----------| |**api**|**ET_Core_API**|Communicate with 3rd-party APIs| |**data**|**ET_Core_Data**|Work with data (consume, format, etc)| |**lib**|**ET_Core_LIB**|3rd-Party Libraries| |**post**|**ET_Core_Post**|Work with WP Objects| |Cache.php|ET_Core_Cache|Simple object cache| |HTTPInterface.php|ET_Core_HTTPInterface|Wrapper for WP's HTTP API| |Logger.php|ET_Core_Logger|Write to the debug log. |PageResource.php|ET_Core_PageResource|Cache inline styles & scripts as static files.| |Portability.php|ET_Core_Portability|Portability import/export| |Rollback.php|ET_Core_VersionRollback|Theme & plugin version rollback| |Updates.php|ET_Core_Updates|Theme & plugin updates| > ***Note:*** Component groups are in **bold**. PKE\7Ucomponents/post/Type.phpnu[name, $this->_category_tax, $this->_tag_tax ); } } PKE\$vcomponents/post/Taxonomy.phpnu[name; /** * Filters the supported post types for a custom taxonomy. The dynamic portion of the * filter name, $name, refers to the name of the custom taxonomy. * * @since 3.0.99 * * @param array */ $this->post_types = apply_filters( "et_core_taxonomy_{$name}_post_types", $this->post_types ); } /** * Get the terms for this taxonomy. * * @return array|int|WP_Error|WP_Term[] */ public function get() { if ( is_null( $this->terms ) ) { $this->terms = get_terms( $this->name, array( 'hide_empty' => false ) ); } return $this->terms; } /** * Get a derived class instance. * * @since 3.0.99 * * @param string $type See {@see self::$wp_type} for accepted values. Default is 'taxonomy'. * @param string $name The name/slug of the derived object. Default is an empty string. * * @return self|null */ public static function instance( $type = 'taxonomy', $name = '' ) { return parent::instance( $type, $name ); } } PKE\\AVVcomponents/post/Object.phpnu[_args = $this->_get_args(); $this->_args['labels'] = $this->_get_labels(); $this->_apply_filters(); $this->_sanity_check(); if ( empty( self::$_instances ) ) { self::$_instances['cpt'] = array(); self::$_instances['taxonomy'] = array(); add_action( 'init', 'ET_Core_Post_Object::register_all' ); } self::$_instances[ $this->wp_type ][ $this->name ] = $this; } /** * Applies filters to the instance's filterable properties. */ protected function _apply_filters() { $name = $this->name; if ( 'cpt' === $this->wp_type ) { /** * Filters the `$args` for a custom post type. The dynamic portion of the * filter, `$name`, refers to the name/key of the post type being registered. * * @since 3.0.99 * * @param array $args {@see register_post_type()} */ $this->_args = apply_filters( "et_core_cpt_{$name}_args", $this->_args ); } else if ( 'taxonomy' === $this->wp_type ) { /** * Filters the `$args` for a custom post taxonomy. The dynamic portion of the * filter, `$name`, refers to the name/key of the taxonomy being registered. * * @since 3.0.99 * * @param array $args {@see register_taxonomy()} */ $this->_args = apply_filters( "et_core_taxonomy_{$name}_args", $this->_args ); } } /** * This method is called right before registering the object. It is intended to be * overridden by child classes as needed. */ protected function _before_register() {} /** * Returns the args for the instance. * See {@see register_post_type()} or {@see register_taxonomy()}. * * @return array $args */ abstract protected function _get_args(); /** * Returns labels for the instance. * See {@see register_post_type()} or {@see register_taxonomy()}. * * @return array $labels */ abstract protected function _get_labels(); /** * Checks for required properties and existing instances. */ protected function _sanity_check() { if ( ! $this->_args || ! $this->name || ! $this->wp_type ) { et_error( 'Missing required properties!' ); wp_die(); } else if ( isset( self::$_instances[ $this->wp_type ][ $this->name ] ) ) { et_error( 'Multiple instances are not allowed!' ); wp_die(); } } /** * Get a derived class instance. * * @since 3.0.99 * * @param string $type See {@see self::$wp_type} for accepted values. Default is 'cpt'. * @param string $name The name/slug of the derived object. Default is an empty string. * * @return self|null */ public static function instance( $type = 'cpt', $name = '' ) { if ( ! self::$_ ) { self::$_ = ET_Core_Data_Utils::instance(); } return self::$_->array_get( self::$_instances, "{$type}.{$name}", null ); } /** * Calls either {@see register_post_type} or {@see register_taxonomy} for each instance. * * @since 3.0.99 * * @param string $owner Optional. Only register objects owned by a part of the codebase. * See {@see self::_owner} for accepted values. */ public static function register_all( $owner = null ) { if ( empty( self::$_instances ) ) { return; } global $wp_taxonomies; foreach ( self::$_instances['taxonomy'] as $name => $instance ) { $can_register = is_null( $owner ) || $owner === $instance->_owner; if ( $instance->_registered || ! $can_register ) { continue; } $instance->_before_register(); register_taxonomy( $name, $instance->post_types, $instance->_args ); $instance->_wp_object = $wp_taxonomies[ $name ]; $instance->_registered = true; } foreach ( self::$_instances['cpt'] as $name => $instance ) { $can_register = is_null( $owner ) || $owner === $instance->_owner; if ( $instance->_registered || ! $can_register ) { continue; } $instance->_before_register(); $instance->_wp_object = register_post_type( $name, $instance->_args ); $instance->_registered = true; } } } PKE\K\components/post/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\Cllcomponents/post/Query.phpnu[post_type = $this->post_type ? $this->post_type : $post_type; $this->category_tax = $this->category_tax ? $this->category_tax : $category_tax; $this->tag_tax = $this->tag_tax ? $this->tag_tax : $tag_tax; $this->_wp_query_args = array( 'post_type' => $this->post_type, 'posts_per_page' => -1, ); if ( ! self::$_ ) { self::$_ = ET_Core_Data_Utils::instance(); } } /** * Adds a meta query to the WP Query args for this instance. * * @since 3.0.99 * * @param string $key The meta key. * @param string $value The meta value. * @param bool $negate Whether or not to negate this meta query. */ protected function _add_meta_query( $key, $value, $negate ) { if ( ! isset( $this->_wp_query_args['meta_query'] ) ) { $this->_wp_query_args['meta_query'] = array(); } if ( is_null( $value ) ) { $compare = $negate ? 'NOT EXISTS' : 'EXISTS'; } else if ( is_array( $value ) ) { $compare = $negate ? 'NOT IN' : 'IN'; } else { $compare = $negate ? '!=' : '='; } $query = array( 'key' => $key, 'compare' => $compare, ); if ( ! is_null( $value ) ) { $query['value'] = $value; } if ( '!=' === $compare ) { $query = array( 'relation' => 'OR', array( 'key' => $key, 'compare' => 'NOT EXISTS', ), $query, ); } $this->_wp_query_args['meta_query'][] = $query; } /** * Adds a tax query to the WP Query args for this instance. * * @since 3.0.99 * * @param string $taxonomy The taxonomy name. * @param array $terms Taxonomy terms. * @param bool $negate Whether or not to negate this tax query. */ protected function _add_tax_query( $taxonomy, $terms, $negate ) { if ( ! isset( $this->_wp_query_args['tax_query'] ) ) { $this->_wp_query_args['tax_query'] = array(); } $operator = $negate ? 'NOT IN' : 'IN'; $field = is_int( $terms[0] ) ? 'term_id' : 'name'; $query = array( 'taxonomy' => $taxonomy, 'field' => $field, 'terms' => $terms, 'operator' => $operator, ); if ( $negate ) { $query = array( 'relation' => 'OR', array( 'taxonomy' => $taxonomy, 'operator' => 'NOT EXISTS', ), $query, ); } $this->_wp_query_args['tax_query'][] = $query; } /** * Resets {@see self::$_negate} to default then returns the previous value. * * @return bool */ protected function _reset_negate() { $negate = $this->_negate; $this->_negate = false; return $negate; } /** * Adds a tax query to this instance's WP Query args for it's category taxonomy. * * @since 3.0.99 * * @param mixed ...$categories Variable number of category arguments where each arg can be * a single category name or ID or an array of names or IDs. * * @return $this */ public function in_category() { $negate = $this->_reset_negate(); if ( ! $this->category_tax ) { et_error( 'A category taxonomy has not been set for this query!' ); return $this; } $args = func_get_args(); $args = self::$_->array_flatten( $args ); if ( ! $args ) { return $this; } $this->_add_tax_query( $this->category_tax, $args, $negate ); return $this; } /** * Negates the next query arg that is set. * * @since 3.0.99 * * @return $this */ public function not() { $this->_negate = true; return $this; } /** * Performs a new WP Query using the instance's current query params and then returns the * results. Typically, this method is the last method call in a set of chained calls to other * methods on this class during which various query params are set. * * Examples: * * $cpt_query * ->in_category( 'some_cat' ) * ->with_tag( 'some_tag' ) * ->run(); * * $cpt_query * ->with_tag( 'some_tag' ) * ->not()->in_category( 'some_cat' ) * ->run(); * * @since 3.0.99 * * @param array $args Optional. Additional arguments for {@see WP_Query}. * * @return WP_Post|WP_Post[] $posts */ public function run( $args = array() ) { if ( ! is_null( $this->_query_result ) ) { return $this->_query_result; } $name = $this->post_type; if ( $args ) { $this->_wp_query_args = array_merge_recursive( $this->_wp_query_args, $args ); } /** * Filters the WP Query args for a custom post type query. The dynamic portion of * the filter name, $name, refers to the name of the custom post type. * * @since 3.0.99 * * @param array $args {@see WP_Query::__construct()} */ $this->_wp_query_args = apply_filters( "et_core_cpt_{$name}_query_args", $this->_wp_query_args ); $query = new WP_Query( $this->_wp_query_args ); $this->_query_result = $query->posts; if ( 1 === count( $this->_query_result ) ) { $this->_query_result = array_pop( $this->_query_result ); } return $this->_query_result; } /** * Adds a meta query to this instance's WP Query args. * * @since 3.0.99 * * @param string $key The meta key. * @param mixed $value Optional. The meta value to compare. When `$value` is not provided, * the comparison will be 'EXISTS' or 'NOT EXISTS' (when negated). * When `$value` is an array, comparison will be 'IN' or 'NOT IN'. * When `$value` is not an array, comparison will be '=' or '!='. * * @return $this */ public function with_meta( $key, $value = null ) { $this->_add_meta_query( $key, $value, $this->_reset_negate() ); return $this; } /** * Adds a tax query to this instance's WP Query args for it's primary tag-like taxonomy. * * @since 3.0.99 * * @param mixed ...$tags Variable number of tag arguments where each arg can be * a single tag name or ID, or an array of tag names or IDs. * * @return $this */ public function with_tag() { $negate = $this->_reset_negate(); if ( ! $this->tag_tax ) { et_error( 'A tag taxonomy has not been set for this query!' ); return $this; } $args = func_get_args(); $args = self::$_->array_flatten( $args ); if ( ! $args ) { return $this; } $this->_add_tax_query( $this->tag_tax, $args, $negate ); return $this; } } PKE\-00components/init.phpnu[singleDeleteCache( $post_id ); } else if ( '' === $post_id && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ) { $GLOBALS['wp_fastest_cache']->deleteCache(); } } // Hummingbird if ( has_action( 'wphb_clear_page_cache' ) ) { '' !== $post_id ? do_action( 'wphb_clear_page_cache', $post_id ) : do_action( 'wphb_clear_page_cache' ); } // WordPress Cache Enabler if ( has_action( 'ce_clear_cache' ) ) { '' !== $post_id ? do_action( 'ce_clear_post_cache', $post_id ) : do_action( 'ce_clear_cache' ); } // LiteSpeed Cache v3.0+. if ( '' !== $post_id && has_action( 'litespeed_purge_post' ) ) { do_action( 'litespeed_purge_post', $post_id ); } elseif ( '' === $post_id && has_action( 'litespeed_purge_all' ) ) { do_action( 'litespeed_purge_all' ); } // LiteSpeed Cache v1.1.3 until v3.0. if ( '' !== $post_id && function_exists( 'litespeed_purge_single_post' ) ) { litespeed_purge_single_post( $post_id ); } elseif ( '' === $post_id && is_callable( 'LiteSpeed_Cache_API::purge_all' ) ) { LiteSpeed_Cache_API::purge_all(); } elseif ( is_callable( 'LiteSpeed_Cache::get_instance' ) ) { // LiteSpeed Cache v1.1.3 below. LiteSpeed_Cache still exist on v2.9.9.2, but no // longer exist on v3.0. Keep it here as backward compatibility for lower version. $litespeed = LiteSpeed_Cache::get_instance(); if ( '' !== $post_id && method_exists( $litespeed, 'purge_post' ) ) { $litespeed->purge_post( $post_id ); } else if ( '' === $post_id && method_exists( $litespeed, 'purge_all' ) ) { $litespeed->purge_all(); } } // Hyper Cache if ( class_exists( 'HyperCache' ) && isset( HyperCache::$instance ) ) { if ( '' !== $post_id && method_exists( HyperCache::$instance, 'clean_post' ) ) { HyperCache::$instance->clean_post( $post_id ); } else if ( '' === $post_id && method_exists( HyperCache::$instance, 'clean' ) ) { HyperCache::$instance->clean_post( $post_id ); } } // Hosting Provider Caching // Pantheon Advanced Page Cache $pantheon_clear = 'pantheon_wp_clear_edge_keys'; $pantheon_clear_all = 'pantheon_wp_clear_edge_all'; if ( function_exists( $pantheon_clear ) || function_exists( $pantheon_clear_all ) ) { if ( '' !== $post_id && function_exists( $pantheon_clear ) ) { pantheon_wp_clear_edge_keys( array( "post-{$post_id}" ) ); } else if ( '' === $post_id && function_exists( $pantheon_clear_all ) ) { pantheon_wp_clear_edge_all(); } } // Siteground if ( isset( $GLOBALS['sg_cachepress_supercacher'] ) ) { global $sg_cachepress_supercacher; if ( is_object( $sg_cachepress_supercacher ) && method_exists( $sg_cachepress_supercacher, 'purge_cache' ) ) { $sg_cachepress_supercacher->purge_cache( true ); } } else if ( function_exists( 'sg_cachepress_purge_cache' ) ) { sg_cachepress_purge_cache(); } // WP Engine if ( class_exists( 'WpeCommon' ) ) { is_callable( 'WpeCommon::purge_memcached' ) ? WpeCommon::purge_memcached() : ''; is_callable( 'WpeCommon::clear_maxcdn_cache' ) ? WpeCommon::clear_maxcdn_cache() : ''; is_callable( 'WpeCommon::purge_varnish_cache' ) ? WpeCommon::purge_varnish_cache() : ''; if ( is_callable( 'WpeCommon::instance' ) && $instance = WpeCommon::instance() ) { method_exists( $instance, 'purge_object_cache' ) ? $instance->purge_object_cache() : ''; } } // Bluehost if ( class_exists( 'Endurance_Page_Cache' ) ) { wp_doing_ajax() ? ET_Core_LIB_BluehostCache::get_instance()->clear( $post_id ) : do_action( 'epc_purge' ); } // Pressable. if ( isset( $GLOBALS['batcache'] ) && is_object( $GLOBALS['batcache'] ) ) { wp_cache_flush(); } // Cloudways - Breeze. if ( class_exists( 'Breeze_Admin' ) ) { $breeze_admin = new Breeze_Admin(); $breeze_admin->breeze_clear_all_cache(); } // Kinsta. if ( class_exists( '\Kinsta\Cache' ) && isset( $GLOBALS['kinsta_cache'] ) && is_object( $GLOBALS['kinsta_cache'] ) ) { global $kinsta_cache; if ( isset( $kinsta_cache->kinsta_cache_purge ) && method_exists( $kinsta_cache->kinsta_cache_purge, 'purge_complete_caches' ) ) { $kinsta_cache->kinsta_cache_purge->purge_complete_caches(); } } // GoDaddy. if ( class_exists( '\WPaaS\Cache' ) ) { global $wpaas_cache_class; // Since GD System Plugin 4.51.1 the cache class instance can be accessed // with $wpaas_cache_class global. In addition to this, the 'has_ban' method // is no longer static. To cover both static and non-static versions we // can test if $wpaas_cache_class exists and use the correct type accordingly. $has_ban = $wpaas_cache_class ? $wpaas_cache_class->has_ban() : \WPaaS\Cache::has_ban(); if ( ! $has_ban ) { $gd_cache_class = $wpaas_cache_class ? $wpaas_cache_class : '\WPaaS\Cache'; remove_action( 'shutdown', array( $gd_cache_class, 'purge' ), PHP_INT_MAX ); add_action( 'shutdown', array( $gd_cache_class, 'ban' ), PHP_INT_MAX ); } } // Complimentary Performance Plugins. // Autoptimize. if ( is_callable( 'autoptimizeCache::clearall' ) ) { autoptimizeCache::clearall(); } // WP Optimize. if ( class_exists( 'WP_Optimize' ) && defined( 'WPO_PLUGIN_MAIN_PATH' ) ) { if ( '' !== $post_id && is_callable( 'WPO_Page_Cache::delete_single_post_cache' ) ) { WPO_Page_Cache::delete_single_post_cache( $post_id ); } elseif ( is_callable( array( 'WP_Optimize', 'get_page_cache' ) ) && is_callable( array( WP_Optimize()->get_page_cache(), 'purge' ) ) ) { WP_Optimize()->get_page_cache()->purge(); } } } catch( Exception $err ) { ET_Core_Logger::error( 'An exception occurred while attempting to clear site cache.' ); } } endif; if ( ! function_exists( 'et_core_get_nonces' ) ): /** * Returns the nonces for this component group. * * @return string[] */ function et_core_get_nonces() { static $nonces = null; return $nonces ? $nonces : $nonces = array( 'clear_page_resources_nonce' => wp_create_nonce( 'clear_page_resources' ), 'et_core_portability_export' => wp_create_nonce( 'et_core_portability_export' ), ); } endif; if ( ! function_exists( 'et_core_page_resource_auto_clear' ) ): function et_core_page_resource_auto_clear() { ET_Core_PageResource::remove_static_resources( 'all', 'all' ); } add_action( 'switch_theme', 'et_core_page_resource_auto_clear' ); add_action( 'activated_plugin', 'et_core_page_resource_auto_clear', 10, 0 ); add_action( 'deactivated_plugin', 'et_core_page_resource_auto_clear', 10, 0 ); endif; if ( ! function_exists( 'et_core_page_resource_clear' ) ): /** * Ajax handler for clearing cached page resources. */ function et_core_page_resource_clear() { et_core_security_check( 'manage_options', 'clear_page_resources' ); if ( empty( $_POST['et_post_id'] ) ) { et_core_die(); } $post_id = sanitize_key( $_POST['et_post_id'] ); $owner = sanitize_key( $_POST['et_owner'] ); ET_Core_PageResource::remove_static_resources( $post_id, $owner ); } add_action( 'wp_ajax_et_core_page_resource_clear', 'et_core_page_resource_clear' ); endif; if ( ! function_exists( 'et_core_page_resource_get' ) ): /** * Get a page resource instance. * * @param string $owner The owner of the instance (core|divi|builder|bloom|monarch|custom). * @param string $slug A string that uniquely identifies the resource. * @param string|int $post_id The post id that the resource is associated with or `global`. * If `null`, the return value of {@link get_the_ID()} will be used. * @param string $type The resource type (style|script). Default: `style`. * @param string $location Where the resource should be output (head|footer). Default: `head-late`. * * @return ET_Core_PageResource */ function et_core_page_resource_get( $owner, $slug, $post_id = null, $priority = 10, $location = 'head-late', $type = 'style' ) { $post_id = $post_id ? $post_id : et_core_page_resource_get_the_ID(); $_slug = "et-{$owner}-{$slug}-{$post_id}-cached-inline-{$type}s"; $all_resources = ET_Core_PageResource::get_resources(); return isset( $all_resources[ $_slug ] ) ? $all_resources[ $_slug ] : new ET_Core_PageResource( $owner, $slug, $post_id, $priority, $location, $type ); } endif; if ( ! function_exists( 'et_core_page_resource_get_the_ID' ) ): function et_core_page_resource_get_the_ID() { static $post_id = null; if ( is_int( $post_id ) ) { return $post_id; } return $post_id = apply_filters( 'et_core_page_resource_current_post_id', get_the_ID() ); } endif; if ( ! function_exists( 'et_core_page_resource_is_singular' ) ): function et_core_page_resource_is_singular() { return apply_filters( 'et_core_page_resource_is_singular', is_singular() ); } endif; if ( ! function_exists( 'et_debug' ) ): function et_debug( $msg, $bt_index = 4, $log_ajax = true ) { ET_Core_Logger::debug( $msg, $bt_index, $log_ajax ); } endif; if ( ! function_exists( 'et_wrong' ) ): function et_wrong( $msg, $error = false ) { $msg = "You're Doing It Wrong! {$msg}"; if ( $error ) { et_error( $msg ); } else { et_debug( $msg ); } } endif; if ( ! function_exists( 'et_error' ) ): function et_error( $msg, $bt_index = 4 ) { ET_Core_Logger::error( "[ERROR]: {$msg}", $bt_index ); } endif; PKE\ s s Acomponents/mu-plugins/SupportCenterSafeModeDisableChildThemes.phpnu[ * @license GNU General Public License v2 */ // Quick exit if accessed directly if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Disable Child Theme (if Safe Mode is active) * * The `is_child_theme()` function returns TRUE if a child theme is active. Parent theme info can be gathered from * the child theme's settings, so in the case of an active child theme we can capture the parent theme's info and * temporarily push the parent theme as active (similar to how WP lets the user preview a theme before activation). * * @since 3.20 * @since 3.23 Moved from `ET_Core_SupportCenter::maybe_disable_child_theme()` for an improved Safe Mode experience. * * @param $current_theme * * @return false|string */ function et_safe_mode_maybe_disable_child_theme( $current_theme ) { // Verbose logging: only log if `wp-config.php` has defined `ET_DEBUG='support_center'` $DEBUG_ET_SUPPORT_CENTER = defined( 'ET_DEBUG' ) && 'support_center' === ET_DEBUG; if ( ! isset( $_COOKIE['et-support-center-safe-mode'] ) ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: No cookie found' ); } return $current_theme; } $verify = get_option( 'et-support-center-safe-mode-verify' ); if ( ! $verify ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: No option found to verify cookie' ); } return $current_theme; } if ( $_COOKIE['et-support-center-safe-mode'] !== $verify ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: Cookie/Option mismatch' ); } return $current_theme; } $template = get_option( 'template' ); if ( $template !== $current_theme ) { return $template; } return $current_theme; } add_filter( 'template', 'et_safe_mode_maybe_disable_child_theme' ); add_filter( 'stylesheet', 'et_safe_mode_maybe_disable_child_theme' ); PKE\LrO[ [ =components/mu-plugins/SupportCenterSafeModeDisablePlugins.phpnu[ * @license GNU General Public License v2 */ // Quick exit if accessed directly if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Disable Plugins (if Safe Mode is active) * * @since 3.20 * * @param array $plugins WP's array of active plugins * * @return array */ function et_safe_mode_maybe_disable_plugins( $plugins = array() ) { // Verbose logging: only log if `wp-config.php` has defined `ET_DEBUG='support_center'` $DEBUG_ET_SUPPORT_CENTER = defined( 'ET_DEBUG' ) && 'support_center' === ET_DEBUG; if ( ! isset( $_COOKIE['et-support-center-safe-mode'] ) ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: No cookie found' ); } return $plugins; } $verify = get_option( 'et-support-center-safe-mode-verify' ); if ( ! $verify ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: No option found to verify cookie' ); } return $plugins; } if ( $_COOKIE['et-support-center-safe-mode'] !== $verify ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: Cookie/Option mismatch' ); } return $plugins; } /** @var array Collection of plugins that we will NOT disable when Safe Mode is activated. */ $plugins_allowlist = (array) get_option( 'et_safe_mode_plugins_allowlist' ); $clean_plugins = $plugins; foreach ( $clean_plugins as $key => &$plugin ) { // Check whether this plugin appears in our allowlist if ( ! in_array( $plugin, $plugins_allowlist ) ) { if ( $DEBUG_ET_SUPPORT_CENTER ) { error_log( 'ET Support Center :: Safe Mode: Unsetting plugin: ' . json_encode( $plugin ) ); } unset( $clean_plugins[ $key ] ); } } return $clean_plugins; } add_filter( 'option_active_plugins', 'et_safe_mode_maybe_disable_plugins' ); add_filter( 'option_active_sitewide_plugins', 'et_safe_mode_maybe_disable_plugins' ); PKE\K\components/mu-plugins/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\Ղ,,components/HTTPInterface.phpnu[URL = esc_url_raw( $url ); $this->METHOD = $method; $this->BODY = $body; $this->IS_AUTH = $is_auth; $this->OWNER = $owner; $this->data_format = null; $this->JSON_BODY = $is_json_body; $this->SSL_VERIFY = $ssl_verify; $this->_set_user_agent(); $this->prepare_args(); } /** * Only include necessary properties when printing this object using {@link var_dump}. * * @return array */ public function __debugInfo() { return array( 'ARGS' => $this->ARGS, 'URL' => $this->URL, 'METHOD' => $this->METHOD, 'BODY' => $this->BODY, 'IS_AUTH' => $this->IS_AUTH, 'IS_JSON_BODY' => $this->JSON_BODY, 'OWNER' => $this->OWNER, ); } /** * Sets the user agent string. */ private function _set_user_agent() { global $wp_version; $owner = $this->OWNER; $version = 'bloom' === $owner ? $GLOBALS['et_bloom']->plugin_version : ET_CORE_VERSION; if ( 'builder' === $owner ) { $owner = 'Divi Builder'; } if ( '' === $owner ) { $this->OWNER = $owner = 'ET_Core'; } else { $owner = ucfirst( $owner ); } $this->USER_AGENT = "WordPress/{$wp_version}; {$owner}/{$version}; " . esc_url_raw( get_bloginfo( 'url' ) ); } /** * Prepares the request arguments (to be passed to wp_remote_*()) */ public function prepare_args() { $this->ARGS = array( 'blocking' => $this->BLOCKING, 'body' => $this->BODY, 'cookies' => $this->COOKIES, 'headers' => $this->HEADERS, 'method' => $this->METHOD, 'sslverify' => $this->SSL_VERIFY, 'user-agent' => $this->USER_AGENT, 'timeout' => 30, ); } } /** * Simple object to hold HTTP response details. * * @since 1.1.0 * * @package ET\Core\HTTP */ class ET_Core_HTTPResponse { /** * @var array */ public $COOKIES; /** * @var string|array */ public $DATA; /** * @var bool */ public $ERROR = false; /** * The error message if `self::$ERROR` is `true`. * * @var string */ public $ERROR_MESSAGE; /** * @var array */ public $HEADERS; /** * @var array|WP_Error */ public $RAW_RESPONSE; /** * @var ET_Core_HTTPRequest */ public $REQUEST; /** * The response's HTTP status code. * * @var int */ public $STATUS_CODE; /** * @var string */ public $STATUS_MESSAGE; /** * ET_Core_HTTP_Response constructor. * * @param ET_Core_HTTPRequest $request * @param array|WP_Error $response */ public function __construct( $request, $response ) { $this->REQUEST = $request; $this->RAW_RESPONSE = $response; $this->_parse_response(); } /** * Parse response and save relevant details. */ private function _parse_response() { if ( is_wp_error( $this->RAW_RESPONSE ) ) { $this->ERROR = true; $this->ERROR_MESSAGE = $this->RAW_RESPONSE->get_error_message(); $this->STATUS_CODE = $this->RAW_RESPONSE->get_error_code(); $this->STATUS_MESSAGE = $this->ERROR_MESSAGE; return; } $this->DATA = $this->RAW_RESPONSE['body']; $this->HEADERS = $this->RAW_RESPONSE['headers']; $this->COOKIES = $this->RAW_RESPONSE['cookies']; $this->STATUS_CODE = $this->RAW_RESPONSE['response']['code']; $this->STATUS_MESSAGE = $this->RAW_RESPONSE['response']['message']; if ( $this->STATUS_CODE >= 400 ) { $this->ERROR = true; $this->ERROR_MESSAGE = $this->STATUS_MESSAGE; } } /** * Only include necessary properties when printing this object using {@link var_dump}. * * @return array */ public function __debugInfo() { return array( 'STATUS_CODE' => $this->STATUS_CODE, 'STATUS_MESSAGE' => $this->STATUS_MESSAGE, 'ERROR' => $this->ERROR, 'ERROR_MESSAGE' => $this->ERROR_MESSAGE, 'DATA' => $this->DATA, ); } /** * Only include necessary properties when serializing this object for * storage in the WP Transient Cache. * * @return array */ public function __sleep() { return array( 'ERROR', 'ERROR_MESSAGE', 'STATUS_CODE', 'STATUS_MESSAGE', 'DATA' ); } } /** * High level, generic, wrapper for making HTTP requests. It uses WordPress HTTP API under-the-hood. * * @since 1.1.0 * * @package ET\Core\HTTP */ class ET_Core_HTTPInterface { /** * How much time responses are cached (in seconds). * * @since 1.1.0 * @var int */ protected $cache_timeout; /** * @var ET_Core_HTTPRequest */ public $request; /** * @var ET_Core_HTTPResponse */ public $response; /** * Whether or not json responses are expected to be received. Default is `true`. * * @var bool */ public $expects_json; /** * The name of the theme/plugin that created this class instance. Default: 'ET_Core'. * * @var string */ public $owner; /** * ET_Core_API_HTTP_Interface constructor. * * @since 1.1.0 * * @param string $owner The name of the theme/plugin that created this class instance. Default: 'ET_Core'. * @param array $request_details Array of config values for the request. Optional. * @param bool $json Whether or not json responses are expected to be received. Default is `true`. */ public function __construct( $owner = 'ET_Core', $request_details = array(), $json = true ) { $this->expects_json = $json; $this->cache_timeout = 15 * MINUTE_IN_SECONDS; $this->owner = $owner; if ( ! empty( $request_details ) ) { list( $url, $method, $is_auth, $body ) = $request_details; $this->prepare_request( $url, $method, $is_auth, $body ); } } /** * Only include necessary properties when printing this object using {@link var_dump}. * * @return array */ public function __debugInfo() { return array( 'REQUEST' => $this->request, 'RESPONSE' => $this->response, ); } /** * Only include necessary properties when serializing this object for * storage in the WP Transient Cache. * * @return array */ public function __sleep() { return array( 'request', 'response' ); } /** * Creates an identifier key for a request based on the URL and body content. * * @internal * @since 1.1.0 * * @param string $url The request URL. * @param string|string[] $body The request body. * * @return string */ protected static function _get_cache_key_for_request( $url, $body ) { if ( is_array( $body ) ) { $url .= json_encode( $body ); } else if ( ! empty( $body ) ) { $url .= $body; } return 'et-core-http-response-' . md5( $url ); } /** * Writes request/response info to the error log for failed requests. * * @internal * @since 1.1.0 */ protected function _log_failed_request() { $details = print_r( $this, true ); $class_name = get_class( $this ); $msg_part = "{$class_name} ERROR :: Remote request failed...\n\n"; $msg = "{$msg_part}Details: {$details}"; $max_len = @ini_get( 'log_errors_max_len' ); @ini_set( 'log_errors_max_len', 0 ); ET_Core_Logger::error( $msg ); if ( $max_len ) { @ini_set( 'log_errors_max_len', $max_len ); } } /** * Prepares request to send JSON data. */ protected function _setup_json_request() { $this->request->HEADERS['Accept'] = 'application/json'; if ( $this->request->JSON_BODY ) { $this->request->HEADERS['Content-Type'] = 'application/json'; $is_json = is_string( $this->request->BODY ) && in_array( $this->request->BODY[0], array( '[', '{' ) ); if ( $is_json || null === $this->request->BODY ) { return; } $this->request->BODY = json_encode( $this->request->BODY ); } } /** * Performs a remote HTTP request. Responses are cached for {@see self::$cache_timeout} seconds using * the {@link https://goo.gl/c0FSMH WP Transients API}. * * @since 1.1.0 */ public function make_remote_request() { $response = null; if ( $this->expects_json && ! isset( $this->request->HEADERS['Content-Type'] ) ) { $this->_setup_json_request(); } // Make sure we include any changes made after request object was instantiated. $this->request->prepare_args(); if ( 'POST' === $this->request->METHOD ) { $response = wp_remote_post( $this->request->URL, $this->request->ARGS ); } else if ( 'GET' === $this->request->METHOD && null === $this->request->data_format ) { $response = wp_remote_get( $this->request->URL, $this->request->ARGS ); } else if ( 'GET' === $this->request->METHOD && null !== $this->request->data_format ) { // WordPress sends data as query args for GET and HEAD requests and provides no way // to alter that behavior. Thus, we need to monkey patch it for now. See the mp'd class // for more details. require_once 'lib/WPHttp.php'; $wp_http = new ET_Core_LIB_WPHttp(); $this->request->ARGS['data_format'] = $this->request->data_format; $response = $wp_http->request( $this->request->URL, $this->request->ARGS ); } else if ( 'PUT' === $this->request->METHOD ) { $this->request->ARGS['method'] = 'PUT'; $response = wp_remote_request( $this->request->URL, $this->request->ARGS ); } $this->response = $response = new ET_Core_HTTPResponse( $this->request, $response ); if ( $response->ERROR || defined( 'ET_DEBUG' ) ) { $this->_log_failed_request(); } if ( $this->expects_json ) { $response->DATA = json_decode( $response->DATA, true ); } $this->request->COMPLETE = true; } /** * Replaces the current request object with a new instance. * * @param string $url * @param string $method * @param bool $is_auth * @param mixed? $body * @param bool $json_body * @param bool $ssl_verify */ public function prepare_request( $url, $method = 'GET', $is_auth = false, $body = null, $json_body = false, $ssl_verify = true ) { $this->request = new ET_Core_HTTPRequest( $url, $method, $this->owner, $is_auth, $body, $json_body, $ssl_verify ); } } PKE\^..updates_init.phpnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\?+i18n/library.phpnu[ esc_html__( 'Snippet', 'et_builder' ), 'Code Snippet' => esc_html__( 'Code Snippet', 'et_builder' ), 'Divi Code Snippets' => esc_html__( 'Divi Code Snippets', 'et_builder' ), 'Code Snippets Library' => esc_html__( 'Code Snippets Library', 'et_builder' ), 'Code Snippet Details' => esc_html__( 'Code Snippet Details', 'et_builder' ), 'CSS Snippet' => esc_html__( 'CSS Snippet', 'et_builder' ), 'Edit Snippet' => esc_html__( 'Edit Snippet', 'et_builder' ), 'HTML/JS Snippet' => esc_html__( 'HTML/JS Snippet', 'et_builder' ), 'Snippets' => esc_html__( 'Snippets', 'et_builder' ), 'importContextFail' => esc_html__( 'This file should not be imported in this context.', 'et_builder' ), 'Edit %s' => esc_html__( 'Edit %s', 'et_builder' ), 'Save' => esc_html__( 'Save', 'et_builder' ), 'Cancel' => esc_html__( 'Cancel', 'et_builder' ), 'Import & Export Snippets' => esc_html__( 'Import & Export Snippets', 'et_builder' ), 'Import & Export Snippet' => esc_html__( 'Import & Export Snippet', 'et_builder' ), 'Import Snippets' => esc_html__( 'Import Snippets', 'et_builder' ), 'Import Snippet' => esc_html__( 'Import Snippet', 'et_builder' ), 'Log In To Divi Cloud' => esc_html__( 'Log In To Divi Cloud', 'et_builder' ), 'Theme Options Library' => esc_html__( 'Theme Options Library', 'et_builder' ), 'Theme Options Details' => esc_html__( 'Theme Options Details', 'et_builder' ), ]; PKE\(php_functions.phpnu[ $val ) { $array[ $key ] = $val; } } else { trigger_error( __FUNCTION__ . '(): Argument #' . ( $i + 1 ) . ' is not an array', E_USER_WARNING ); return null; } } return $array; } endif; PKE\@N,,'item-library-local/ItemLibraryLocal.phpnu[ $new_name ) ); if ( ! is_wp_error( $updated_term_data ) ) { $new_terms[] = array( 'name' => $new_name, 'id' => $updated_term_data['term_id'], 'location' => 'local', ); } } break; case 'add': $term_name = (string) $single_item['id']; $new_term_data = wp_insert_term( $term_name, $taxonomy ); if ( ! is_wp_error( $new_term_data ) ) { $new_terms[] = array( 'name' => $term_name, 'id' => $new_term_data['term_id'], 'location' => 'local', ); } break; } } return array( 'newFilters' => $new_terms, 'filterType' => $filter_type, 'localLibraryTerms' => [ 'layout_category' => $this->get_processed_terms( 'layout_category' ), 'layout_tag' => $this->get_processed_terms( 'layout_tag' ), ], ); } /** * Gets the terms list and processes it into desired format. * * @since 4.18.0 * * @param string $term_name Term Name. * * @return array $terms_by_id */ public function get_processed_terms( $term_name ) { $terms = get_terms( $term_name, array( 'hide_empty' => false ) ); $terms_by_id = array(); if ( is_wp_error( $terms ) || empty( $terms ) ) { return array(); } foreach ( $terms as $term ) { $term_id = $term->term_id; $terms_by_id[ $term_id ]['id'] = $term_id; $terms_by_id[ $term_id ]['name'] = $term->name; $terms_by_id[ $term_id ]['slug'] = $term->slug; $terms_by_id[ $term_id ]['count'] = $term->count; } return $terms_by_id; } /** * Processes item taxonomies for inclusion in the library UI items data. * * @since 4.18.0 * * @param WP_POST $post Unprocessed item. * @param object $item Currently processing item. * @param int $index The item's index position. * @param array[] $item_terms Processed items. * @param string $taxonomy_name Item name. * @param string $type Item type. * * @return void */ public function process_item_taxonomy( $post, $item, $index, &$item_terms, $taxonomy_name, $type ) { $terms = wp_get_post_terms( $post->ID, $taxonomy_name ); if ( ! $terms ) { if ( 'category' === $type ) { $item->category_slug = 'uncategorized'; } return; } foreach ( $terms as $term ) { $term_name = et_core_intentionally_unescaped( $term->name, 'react_jsx' ); if ( ! isset( $item_terms[ $term->term_id ] ) ) { $item_terms[ $term->term_id ] = array( 'id' => $term->term_id, 'name' => $term_name, 'slug' => $term->slug, 'items' => array(), ); } $item_terms[ $term->term_id ]['items'][] = $index; if ( 'category' === $type ) { $item->categories[] = $term_name; } else { $item->tags[] = $term_name; } $item->{$type . '_ids'}[] = $term->term_id; if ( ! isset( $item->{$type . '_slug'} ) ) { $item->{$type . '_slug'} = $term->slug; } $id = get_post_meta( $post->ID, "_primary_{$taxonomy_name}", true ); if ( $id ) { // $id is a string, $term->term_id is an int. if ( $id === $term->term_id ) { // This is the primary term (used in the item URL). $item->{$type . '_slug'} = $term->slug; } } } } /** * Update library item. Support following updates: * - Duplicate * - Rename * - Toggle Favorite status * - Delete * - Delete Permanently * - Restore * * @since 4.21.0 * * @param array $payload Array with the id and update details. * * @return array Updated item details */ protected function _perform_item_common_updates( $payload ) { if ( empty( $payload['item_id'] ) || empty( $payload['update_details'] ) ) { return false; } $update_details = $payload['update_details']; if ( empty( $update_details['updateType'] ) ) { return false; } $et_builder_categories = ET_Builder_Post_Taxonomy_LayoutCategory::instance(); $et_builder_tags = ET_Builder_Post_Taxonomy_LayoutTag::instance(); $new_id = 0; $item_id = absint( $payload['item_id'] ); $item_update = array( 'ID' => $item_id ); $update_type = sanitize_text_field( $update_details['updateType'] ); $item_name = isset( $update_details['itemName'] ) ? sanitize_text_field( $update_details['itemName'] ) : ''; $favorite_status = isset( $update_details['favoriteStatus'] ) && ( 'on' === $update_details['favoriteStatus'] ) ? 'favorite' : ''; $categories = isset( $update_details['itemCategories'] ) ? array_unique( array_map( 'absint', $update_details['itemCategories'] ) ) : array(); $tags = isset( $update_details['itemTags'] ) ? array_unique( array_map( 'absint', $update_details['itemTags'] ) ) : array(); $post_type = get_post_type( $item_id ); if ( ! empty( $update_details['newCategoryName'] ) ) { $categories = $this->_create_and_get_all_item_terms( $update_details['newCategoryName'], $categories, $et_builder_categories->name ); } if ( ! empty( $update_details['newTagName'] ) ) { $tags = $this->_create_and_get_all_item_terms( $update_details['newTagName'], $tags, $et_builder_tags->name ); } if ( in_array( $update_type, $this->exceptional_processes, true ) ) { $update_type = 'default'; } switch ( $update_type ) { case 'duplicate': case 'duplicate_and_delete': break; case 'rename': if ( ! current_user_can( 'edit_post', $item_id ) || $this->post_type !== $post_type ) { return; } if ( $item_name ) { $item_update['post_title'] = $item_name; wp_update_post( $item_update ); } break; case 'toggle_fav': update_post_meta( $item_id, 'favorite_status', $favorite_status ); break; case 'delete': if ( ! current_user_can( 'edit_post', $item_id ) || $this->post_type !== $post_type ) { return; } wp_trash_post( $item_id ); break; case 'delete_permanently': if ( ! current_user_can( 'edit_post', $item_id ) || $this->post_type !== $post_type ) { return; } wp_delete_post( $item_id, true ); break; case 'restore': if ( ! current_user_can( 'edit_post', $item_id ) || $this->post_type !== $post_type ) { return; } $publish_fn = function() { return 'publish'; }; // wp_untrash_post() restores the post to `draft` by default, we have to set `publish` status via filter. add_filter( 'wp_untrash_post_status', $publish_fn ); wp_untrash_post( $item_id ); remove_filter( 'wp_untrash_post_status', $publish_fn ); break; case 'edit_cats': wp_set_object_terms( $item_id, $categories, $et_builder_categories->name ); wp_set_object_terms( $item_id, $tags, $et_builder_tags->name ); break; } // Continue with additional data. $processed_new_categories = array(); $processed_new_tags = array(); $updated_categories = get_terms( array( 'taxonomy' => $et_builder_categories->name, 'hide_empty' => false, ) ); $updated_tags = get_terms( array( 'taxonomy' => $et_builder_tags->name, 'hide_empty' => false, ) ); if ( ! empty( $updated_categories ) ) { foreach ( $updated_categories as $single_category ) { $processed_new_categories[] = array( 'id' => $single_category->term_id, 'name' => $single_category->name, 'count' => $single_category->count, 'location' => 'local', ); } } if ( ! empty( $updated_tags ) ) { foreach ( $updated_tags as $single_tag ) { $processed_new_tags[] = array( 'id' => $single_tag->term_id, 'name' => $single_tag->name, 'count' => $single_tag->count, 'location' => 'local', ); } } return array( 'updatedItem' => $item_id, 'newItem' => $new_id, 'updateType' => $update_type, 'categories' => $categories, 'tags' => $tags, 'updatedTerms' => array( 'categories' => $processed_new_categories, 'tags' => $processed_new_tags, ), ); } /** * Get all terms of an item and merge any newly passed IDs with the list. * * @since 4.19.0 * * @param string $new_terms_list List of new terms. * @param array $taxonomies Taxonomies. * @param string $taxonomy_name Taxonomy name. * * @return array */ private function _create_and_get_all_item_terms( $new_terms_list, $taxonomies, $taxonomy_name ) { $new_names_array = explode( ',', $new_terms_list ); foreach ( $new_names_array as $new_name ) { if ( '' !== $new_name ) { $new_term = wp_insert_term( $new_name, $taxonomy_name ); if ( ! is_wp_error( $new_term ) ) { $taxonomies[] = $new_term['term_id']; } elseif ( ! empty( $new_term->error_data ) && ! empty( $new_term->error_data['term_exists'] ) ) { $taxonomies[] = $new_term->error_data['term_exists']; } } } return $taxonomies; } /** * Prepare Library Categories or Tags List. * * @param string $taxonomy Name of the taxonomy. * * @return array Clean Categories/Tags array. **/ public function get_formatted_library_terms( $taxonomy = 'layout_category' ) { $raw_terms_array = apply_filters( 'et_pb_new_layout_cats_array', get_terms( $taxonomy, array( 'hide_empty' => false ) ) ); $formatted_terms_array = array(); if ( is_array( $raw_terms_array ) && ! empty( $raw_terms_array ) ) { foreach ( $raw_terms_array as $term ) { $formatted_terms_array[] = array( 'name' => et_core_intentionally_unescaped( html_entity_decode( $term->name ), 'react_jsx' ), 'id' => $term->term_id, 'slug' => $term->slug, 'count' => $term->count, ); } } return $formatted_terms_array; } } PKE\K\item-library-local/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\f!z!zbuild/et-core-app.bundle.cssnu[/*! This minified app bundle contains open source software from several third party developers. Please review CREDITS.md in the root directory or LICENSE.md in the current directory for complete licensing, copyright and patent information. This file and the included code may not be redistributed without the attributions listed in LICENSE.md, including associate copyright notices and licensing information. */ @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.et-common-branded-modal__header{z-index:1000}.et-common-branded-modal{font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;line-height:16px;border-radius:3px;-webkit-box-shadow:0 5px 30px rgba(43,135,218,0.2);box-shadow:0 5px 30px rgba(43,135,218,0.2);background:#fff;border-radius:3px;box-shadow:0 5px 30px rgba(43,135,218,0.2)}@media (max-width: 812px){.et-common-branded-modal{border-radius:0}}.et-common-branded-modal--fullheight{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;height:100%}.et-common-branded-modal__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;background:#6C2EB9;height:58px;border-radius:3px 3px 0 0;padding:0 14px 0 26px;color:#fff;font-size:18px;font-weight:600;line-height:24px;text-transform:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.et-tb-branded-modal--visual-builder .et-common-branded-modal__header{font-size:16px}.rtl .et-common-branded-modal__header{padding:0 18px 0 18px}@media (max-width: 812px){.et-common-branded-modal__header{border-radius:0}}.et-common-branded-modal--fullheight .et-common-branded-modal__header{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto}.et-common-branded-modal--visual-builder .et-common-branded-modal__header{height:32px}.et-common-branded-modal__title{max-width:80%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}.et-common-branded-modal__header-buttons{display:-webkit-box;display:-ms-flexbox;display:flex} .et-common-button{-webkit-box-sizing:border-box;box-sizing:border-box;position:relative;padding:12px;border:0;border-radius:3px;margin:0;line-height:16px;font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;font-size:14px;font-weight:600;background:transparent;color:#fff;outline:none;cursor:pointer;-webkit-transition:background 200ms ease;transition:background 200ms ease;overflow:hidden}a.et-common-button{text-align:center;text-decoration:none;display:inline-block}a.et-common-button:hover,a.et-common-button:focus{color:#fff;border:none;outline:none;-webkit-box-shadow:none;box-shadow:none}.et-common-button--round{border-radius:100px}.et-common-button--round .et-fb-icon{display:block}.et-common-button--compact{padding:8px}.et-common-button--rectangle{border-radius:3px;background:#f1f4f9;color:#5c6978}.et-common-button--primary{background:#2B87DA;color:#fff}.et-common-button--danger{background:#EF5555;color:#fff}.et-common-button--success{background:#29C4A9;color:#fff}.et-common-button--secondary{background:#29C4A9;color:#fff}.et-common-button--cancel{background:#ED5759;color:#fff}.et-common-button--tertiary{background:#7D3BCF;color:#fff}.et-common-button--meta{padding:6px;color:#fff;background:#a3b0c2;-webkit-box-shadow:5px 5px 15px rgba(43,135,218,0.15);box-shadow:5px 5px 15px rgba(43,135,218,0.15);-webkit-transition:padding 0.25s ease-in-out, margin 0.25s ease-in-out, bottom 0.25s ease-in-out;transition:padding 0.25s ease-in-out, margin 0.25s ease-in-out, bottom 0.25s ease-in-out}.et-common-button--meta:hover{padding:12px;margin:-6px} .et-common-icon{display:inline-block;vertical-align:middle}.et-common-icon svg{display:block;width:100%;fill:inherit}.et-common-icon.et-common-icon--divi-ai-light svg .cls-1{fill:url(#divi-ai-light-linear-gradient)}.et-common-icon.et-common-icon--divi-ai-light svg .cls-2{fill:#fff} @-webkit-keyframes et-common-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes et-common-fade-in{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes et-common-slide-fade-in{0%{-webkit-transform:translate(-30px, 0);transform:translate(-30px, 0);opacity:0}100%{-webkit-transform:translate(0, 0);transform:translate(0, 0);opacity:1}}@keyframes et-common-slide-fade-in{0%{-webkit-transform:translate(-30px, 0);transform:translate(-30px, 0);opacity:0}100%{-webkit-transform:translate(0, 0);transform:translate(0, 0);opacity:1}}@-webkit-keyframes et-common-zoom-in{0%{-webkit-transform:scale(0.5, 0.5);transform:scale(0.5, 0.5)}100%{-webkit-transform:scale(1, 1);transform:scale(1, 1)}}@keyframes et-common-zoom-in{0%{-webkit-transform:scale(0.5, 0.5);transform:scale(0.5, 0.5)}100%{-webkit-transform:scale(1, 1);transform:scale(1, 1)}}@-webkit-keyframes et-common-bounce-in{from,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1)}0%{opacity:0;-webkit-transform:scale3d(0.3, 0.3, 0.3);transform:scale3d(0.3, 0.3, 0.3)}20%{-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}40%{-webkit-transform:scale3d(0.9, 0.9, 0.9);transform:scale3d(0.9, 0.9, 0.9)}60%{opacity:1;-webkit-transform:scale3d(1.03, 1.03, 1.03);transform:scale3d(1.03, 1.03, 1.03)}80%{-webkit-transform:scale3d(0.97, 0.97, 0.97);transform:scale3d(0.97, 0.97, 0.97)}to{opacity:1;-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}@keyframes et-common-bounce-in{from,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1)}0%{opacity:0;-webkit-transform:scale3d(0.3, 0.3, 0.3);transform:scale3d(0.3, 0.3, 0.3)}20%{-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}40%{-webkit-transform:scale3d(0.9, 0.9, 0.9);transform:scale3d(0.9, 0.9, 0.9)}60%{opacity:1;-webkit-transform:scale3d(1.03, 1.03, 1.03);transform:scale3d(1.03, 1.03, 1.03)}80%{-webkit-transform:scale3d(0.97, 0.97, 0.97);transform:scale3d(0.97, 0.97, 0.97)}to{opacity:1;-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}.et-common-progress-bar{width:350px;left:50%;top:53%;position:absolute;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.et-common-progress-bar__background{background:#F1F5F9}.et-common-progress-bar__bar{border-radius:3px;background-color:#32C4AA;background-image:linear-gradient(-45deg, rgba(255,255,255,0.3) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.3) 50%, rgba(255,255,255,0.3) 75%, transparent 75%, transparent);background-size:30px 30px;-webkit-animation:et-core-progress-bar-stripes 2s linear infinite;animation:et-core-progress-bar-stripes 2s linear infinite;width:0%;-webkit-transition:width 0.4s ease;transition:width 0.4s ease}.et-common-progress-bar__value{min-width:30px;font-weight:700;line-height:22px;text-align:center;color:#fff}.et-common-progress-bar__estimate{padding:10px 0;text-align:center;font-weight:600;color:#A6A9B2}.et-common-loader{background:transparent;-webkit-transition:background, -webkit-box-shadow 0.3s;transition:background, -webkit-box-shadow 0.3s;transition:background, box-shadow 0.3s;transition:background, box-shadow 0.3s, -webkit-box-shadow 0.3s;height:50px;width:50px;color:#fff;border-radius:50px;text-align:center;-webkit-box-shadow:rgba(0,139,219,0.25) 0 0 60px;box-shadow:rgba(0,139,219,0.25) 0 0 60px;display:block;margin:auto}.et-common-loader-success{opacity:0;-webkit-animation:et-common-bounce-in 1s;animation:et-common-bounce-in 1s;-webkit-animation-delay:0.3s;animation-delay:0.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;background:#a9e900;-webkit-box-shadow:rgba(169,233,0,0.25) 0 0 60px;box-shadow:rgba(169,233,0,0.25) 0 0 60px}.et-common-loader-success:before{font-family:'ETmodules';content:'\4e';font-weight:600;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:30px;line-height:53px} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.et-common-app-spinner-block{position:relative;height:80px}.et-common-app-spinner-block--overlay{position:absolute;z-index:100;left:0;top:0;width:100%;height:100%;background:#fff}.et-common-app-spinner-block__spinner{position:absolute;background:none;width:80px;height:80px;left:calc(50% - 40px);top:calc(50% - 40px);right:auto;bottom:auto}.et-common-app-spinner-block__spinner:before{content:'';position:absolute;top:50%;left:50%;width:12px;height:12px;border-radius:12px;-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #7E3BD0,0 17px #7E3BD0,-17px 0 #7E3BD0;box-shadow:0 -17px #7E3BD0,17px 0 #7E3BD0,0 17px #7E3BD0,-17px 0 #7E3BD0;margin:-6px auto auto -6px;-webkit-animation:et-spinner ease infinite 3s;animation:et-spinner ease infinite 3s} .et-common-tabs-navigation{display:-webkit-box;display:-ms-flexbox;display:flex;background:#7E3BD0}.et-common-tabs-navigation__button{display:block;padding:13px 26px;border:0;font-size:14px !important;font-weight:600 !important;line-height:1 !important;color:#fff !important;background:#7E3BD0;outline:none;-webkit-transition:background 200ms ease,opacity 150ms ease,-webkit-transform 200ms ease;transition:background 200ms ease,opacity 150ms ease,-webkit-transform 200ms ease;transition:background 200ms ease,transform 200ms ease,opacity 150ms ease;transition:background 200ms ease,transform 200ms ease,opacity 150ms ease,-webkit-transform 200ms ease;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.et-common-tabs-navigation__button:hover{background:#7435C1}.et-common-tabs-navigation__button--active,.et-common-tabs-navigation__button--active:hover{background:#8E42EB}.et-common-tabs-navigation__button svg{fill:#fff} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}body.et-common-prompt-open *{pointer-events:none}body.et-common-prompt-open .et-common-prompt,body.et-common-prompt-open .et-common-prompt *{pointer-events:auto}body.et-common-prompt-open{overflow:hidden}.et-common-prompt{position:fixed;left:0;top:0;width:100vw;height:100vh}.et-common-prompt-draggable{width:calc(100vw - 15px)}.et-common-prompt{z-index:2000000}.et-common-prompt__overlay{position:fixed;left:0;top:0;width:100vw;height:100vh;background:radial-gradient(ellipse at center, #fff 20%, rgba(255,255,255,0) 80%);-webkit-animation:et-common-fade-in 200ms ease;animation:et-common-fade-in 200ms ease}.et-common-prompt__modal{position:fixed;left:0;top:0;width:100vw;height:100vh}.et-common-prompt-draggable .et-common-prompt__modal{width:calc(100vw - 15px)}body.admin-bar .et-common-prompt-draggable .et-common-prompt__modal{top:32px;height:calc(100vh - 32px)}.et-common-prompt__modal{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.et-common-prompt__container{width:400px;max-width:100%;-webkit-box-shadow:0 5px 30px rgba(43,135,218,0.2);box-shadow:0 5px 30px rgba(43,135,218,0.2)}@media (max-width: 812px){.et-common-prompt__container{width:100%}}.et-common-prompt__header{display:-webkit-box;display:-ms-flexbox;display:flex;position:relative;padding:9px 26px;border-radius:3px 3px 0 0;font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;font-weight:600;font-size:18px;line-height:40px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#fff;background-color:#6C2EB9;-webkit-box-shadow:0 5px 30px rgba(0,0,0,0.1);box-shadow:0 5px 30px rgba(0,0,0,0.1);-webkit-box-shadow:none;box-shadow:none;padding-right:9px}.rtl .et-common-prompt__header{padding-right:18px !important;padding-left:9px !important}.et-common-prompt__header-back{padding-left:9px}@media (max-width: 812px){.et-common-prompt__header{margin-top:0;border-radius:0}}.react-draggable .et-common-prompt__header{cursor:move}.et-common-prompt__header-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-left:auto}.rtl .et-common-prompt__header-actions{margin-left:0 !important;margin-right:auto}.et-common-prompt__header-actions .et-fb-icon svg{fill:#fff}.et-common-prompt__body{background:#fff}@media (max-width: 812px){.et-common-prompt__body{height:calc(100vh - 58px - 42px)}}.et-common-prompt__content{color:#4C5866;padding:30px}.et-common-prompt__content p{margin:0 0 13px 0;font-weight:600}.et-common-prompt__content ul{padding:0 0 0 25px;list-style-type:disc}.et-common-prompt__content>*:last-child{margin-bottom:0}.et-common-prompt__footer{display:-webkit-box;display:-ms-flexbox;display:flex;border-radius:0 0 3px 3px}.et-common-prompt__footer .et-common-button{-webkit-box-flex:1;-ms-flex:1 0 0px;flex:1 0 0;padding:10px;font-weight:700;line-height:20px;border-radius:0}.et-common-prompt__footer .et-common-button:first-child{border-bottom-left-radius:3px}.et-common-prompt__footer .et-common-button:last-child{border-bottom-right-radius:3px}.rtl .et-common-prompt__footer .et-common-button:first-child{border-bottom-left-radius:0;border-bottom-right-radius:3px}.rtl .et-common-prompt__footer .et-common-button:last-child{border-bottom-right-radius:0;border-bottom-left-radius:3px}.rtl .et-common-prompt__footer .et-common-button:first-child:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}@media (max-width: 812px){.et-common-prompt__footer{border-radius:0}.et-common-prompt__footer .et-common-button{border-radius:0 !important}} body.et-common-scroll-lock{overflow:hidden} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}[type].et-common-input-text{display:inline-block;background:#F1F5F9;max-height:30px;border:0;border-radius:3px;padding:7px 10px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background 200ms ease;transition:background 200ms ease;color:#4C5866;font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;font-size:13px;font-weight:600;text-transform:none;line-height:normal;-webkit-box-shadow:none;box-shadow:none;letter-spacing:normal}[type].et-common-input-text:focus{-webkit-box-shadow:none;box-shadow:none;background:#E6ECF2;text-transform:none;letter-spacing:normal}[type].et-common-input-text::-webkit-input-placeholder{color:#98a7b8;text-transform:none;letter-spacing:normal}[type].et-common-input-text:-moz-placeholder{color:#98a7b8;text-transform:none;letter-spacing:normal}[type].et-common-input-text::-moz-placeholder{color:#98a7b8;text-transform:none;letter-spacing:normal}[type].et-common-input-text:-ms-input-placeholder{color:#98a7b8;text-transform:none;letter-spacing:normal}[type].et-common-input-text--block{display:block;width:100%}[type].et-common-input-text[readonly]{background:#ffffff !important;border:1px solid #EAEDF0 !important;cursor:not-allowed} @-webkit-keyframes et-common-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes et-common-fade-in{0%{opacity:0}100%{opacity:1}}@-webkit-keyframes et-common-slide-fade-in{0%{-webkit-transform:translate(-30px, 0);transform:translate(-30px, 0);opacity:0}100%{-webkit-transform:translate(0, 0);transform:translate(0, 0);opacity:1}}@keyframes et-common-slide-fade-in{0%{-webkit-transform:translate(-30px, 0);transform:translate(-30px, 0);opacity:0}100%{-webkit-transform:translate(0, 0);transform:translate(0, 0);opacity:1}}@-webkit-keyframes et-common-zoom-in{0%{-webkit-transform:scale(0.5, 0.5);transform:scale(0.5, 0.5)}100%{-webkit-transform:scale(1, 1);transform:scale(1, 1)}}@keyframes et-common-zoom-in{0%{-webkit-transform:scale(0.5, 0.5);transform:scale(0.5, 0.5)}100%{-webkit-transform:scale(1, 1);transform:scale(1, 1)}}@-webkit-keyframes et-common-bounce-in{from,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1)}0%{opacity:0;-webkit-transform:scale3d(0.3, 0.3, 0.3);transform:scale3d(0.3, 0.3, 0.3)}20%{-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}40%{-webkit-transform:scale3d(0.9, 0.9, 0.9);transform:scale3d(0.9, 0.9, 0.9)}60%{opacity:1;-webkit-transform:scale3d(1.03, 1.03, 1.03);transform:scale3d(1.03, 1.03, 1.03)}80%{-webkit-transform:scale3d(0.97, 0.97, 0.97);transform:scale3d(0.97, 0.97, 0.97)}to{opacity:1;-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}@keyframes et-common-bounce-in{from,20%,40%,60%,80%,to{-webkit-animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1);animation-timing-function:cubic-bezier(0.215, 0.61, 0.355, 1)}0%{opacity:0;-webkit-transform:scale3d(0.3, 0.3, 0.3);transform:scale3d(0.3, 0.3, 0.3)}20%{-webkit-transform:scale3d(1.1, 1.1, 1.1);transform:scale3d(1.1, 1.1, 1.1)}40%{-webkit-transform:scale3d(0.9, 0.9, 0.9);transform:scale3d(0.9, 0.9, 0.9)}60%{opacity:1;-webkit-transform:scale3d(1.03, 1.03, 1.03);transform:scale3d(1.03, 1.03, 1.03)}80%{-webkit-transform:scale3d(0.97, 0.97, 0.97);transform:scale3d(0.97, 0.97, 0.97)}to{opacity:1;-webkit-transform:scale3d(1, 1, 1);transform:scale3d(1, 1, 1)}}.et-common-checkbox{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;padding:3px;font-size:13px;font-weight:600;color:#4C5866;line-height:normal}.et-common-checkbox__input[type="checkbox"]{-webkit-box-flex:0;-ms-flex:0 0 24px;flex:0 0 24px;width:24px;height:24px;padding:0;margin:0 8px 0 0;border:0;border-radius:3px;background:#f1f4f9;-webkit-box-shadow:none;box-shadow:none;-webkit-appearance:none}.rtl .et-common-checkbox__input[type="checkbox"]{margin:0 0 0 8px}.et-common-checkbox__input[type="checkbox"]:focus{outline:none;-webkit-box-shadow:none;box-shadow:none}.et-common-checkbox__input[type="checkbox"]:disabled,.et-common-checkbox__input[type="checkbox"]:disabled:checked:before{opacity:1}.et-common-checkbox__input[type="checkbox"]:checked{position:relative}.et-common-checkbox__input[type="checkbox"]:checked:before{content:"\f147";display:inline-block;position:absolute;margin:0 0 0 -1px;top:50%;left:50%;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);color:#00c3aa;font:400 24px/1 dashicons;height:auto;width:auto}.rtl .et-common-checkbox__input[type="checkbox"]:checked:before{margin:0 !important}.et-common-checkbox__input--danger[type="checkbox"]:checked:before{color:#EF5555}.et-common-checkbox__label{-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0;line-height:24px;-webkit-transition:color 200ms ease;transition:color 200ms ease}.et-common-checkbox__label .et-fb-icon{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;position:relative;top:4px}.et-common-checkbox__label .et-fb-icon svg{fill:#a3b0c2;-webkit-transition:fill 200ms ease;transition:fill 200ms ease}.et-common-checkbox-group{padding-bottom:16px}.et-common-checkbox-group+.et-common-checkbox-group{padding-top:16px;border-top:2px solid #e7eef5}.et-common-checkbox-group:last-child{padding-bottom:0}.et-common-checkbox-group__label{display:block;margin-bottom:7px;font-size:13px;font-weight:600;color:#a3b0c2;cursor:auto}.et-common-checkbox-group__list{padding:0;margin:0;list-style-type:none}.et-common-checkbox-group__list li{padding:0;margin:0} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.et-common-library-portability-modal{-webkit-font-smoothing:antialiased}.et-common-library-portability-modal__spinner-overlay{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;height:calc(100% - 60px);-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:absolute;top:60px;width:100%;z-index:99}.et-common-library-portability-modal .et-common-prompt__header .et-common-button{background:transparent !important}.et-common-library-portability-modal .et-common-button--primary{background:#2B87DA !important;color:#fff !important}.et-common-library-portability-modal .et-common-prompt__overlay,.et-common-library-portability-modal .et-common-prompt__modal{height:100%;width:100%}.et-common-library-portability-modal .et-common-prompt__container{position:relative}.et-common-library-portability-modal .et-common-prompt .et-common-export-file-container h3,.et-common-library-portability-modal .et-common-prompt .et-common-import-file-container h3{color:#32373c;font-size:14px;font-weight:600;font-family:inherit;margin:0;padding-bottom:10px}.et-common-library-portability-modal .et-common-prompt .et-common-export-file-container p,.et-common-library-portability-modal .et-common-prompt .et-common-import-file-container p{font-size:13px;padding:0}.et-common-library-portability-modal .et-common-prompt .et-common-export-file-container .et-common-input-text,.et-common-library-portability-modal .et-common-prompt .et-common-import-file-container .et-common-input-text{width:100%}.et-common-library-portability-modal .et-common-prompt button{font-weight:600}.et-common-library-portability-modal .et-common-import-file-container{position:relative}.et-common-library-portability-modal .et-common-import-file-container .et-common-import-file-name-field{height:54px;margin-bottom:20px}.et-common-library-portability-modal .et-common-import-file-container .et-common-import-file{cursor:pointer;height:30px;left:0;opacity:0;position:absolute;width:100%}.et-common-library-portability-modal .et-common-import-file-container .et-common-portability-import-placeholder{border:2px dashed #e6ecf2;border-radius:3px;color:#a3b0c2;float:left;font-size:12px;font-weight:700;height:16px;line-height:16px;overflow:hidden;padding:5px;text-align:center;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap;width:326px}.et-common-library-portability-modal .et-common-import-file-container .et-common-portability-import-placeholder--active{border-color:#2B87DA;border-style:solid;color:#2B87DA}.et-common-library-portability-modal .et-common-import-file-container .et-common-checkbox{padding:0}.et-common-library-portability-modal .et-common-import-file-container .et-common-checkbox__input::before{margin:0 !important}.toplevel_page_et_divi_options .et-common-library-portability-modal .et-common-import-file-container .et-common-checkbox__label{line-height:16px}.et-common-library-portability-modal .et-common-import-file-container .et-common-import-error-container p{margin:0 0 13px 0;color:red;font-weight:600}.et-common-library-portability-modal .et-common-button-disabled{pointer-events:none}body.et-fb .et-common-library-portability-modal .et-common-portability-import-placeholder{height:30px} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.et-common-library-overlay{position:fixed;left:0;top:0;width:100vw;height:100vh;background:radial-gradient(ellipse at center, #fff 20%, rgba(255,255,255,0.7) 100%);z-index:159900;-webkit-animation:et-core-fade-in 500ms linear;animation:et-core-fade-in 500ms linear}.et-common-library-modal-positioner{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;position:fixed;left:30px;top:32px;right:30px;bottom:30px;z-index:159900;-webkit-font-smoothing:antialiased}.et-common-library-modal{font-size:13px;-webkit-box-flex:1;-ms-flex:1 1 0px;flex:1 1 0}@media (min-width: 813px){.et-common-library-modal{position:relative;left:0 !important;right:0 !important;top:0 !important;bottom:0 !important}.et-common-library-modal #et-cloud-app .et-cloud-app-layout-screenshot{height:100%;max-height:100%}}.et-common-library-modal .et-common-branded-modal__header .et-common-button{background-color:transparent !important}.et-common-library-modal .et-common-branded-modal__header .et-common-button:focus{outline:none}.et-common-library-modal #et-cloud-app.et-common-library-cloud .et-cloud-app-content-wrapper{top:58px}.et-common-library-modal #et-cloud-app.et-common-library-cloud .et-cloud-app-content-wrapper .et-cloud-app-layout{height:calc(100% - 58px);overflow-y:auto}.et-common-library-modal #et-cloud-app.et-common-library-cloud .et-cloud-app-content-wrapper .et-cloud-app-view-header,.et-common-library-modal #et-cloud-app.et-common-library-cloud .et-cloud-app-content-wrapper .et-cloud-filter{font-weight:600}.et-common-library-modal #et-cloud-app.et-common-library-cloud .et-cloud-app-content-wrapper .et-cloud-filter-editor-add-new{line-height:1.7em}.et-common-library-modal #et-cloud-app.et-common-library-cloud .et-cloud-app-content-wrapper .et-cloud-editor-control h6{padding-bottom:10px}.et-common-button.et-code-snippets-library__back-button{margin-left:-40px;opacity:0;pointer-events:none;-webkit-transition:opacity 200ms ease,margin-left 500ms cubic-bezier(0.175, 0.885, 0.35, 1.42);transition:opacity 200ms ease,margin-left 500ms cubic-bezier(0.175, 0.885, 0.35, 1.42)}.et-common-button.et-code-snippets-library__back-button--visible{pointer-events:auto;margin-left:-12px;opacity:1}.et-common-button.et-code-snippets-library__back-button--visible .et-common-icon{margin-top:-11px !important}.rtl .et-common-button.et-code-snippets-library__back-button--visible{margin-left:0} .et-common-toggle{display:table;background:#f1f5f9;border-radius:3px;padding:5px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:background-color 200ms ease,color 200ms ease;transition:background-color 200ms ease,color 200ms ease;color:#A4AFC0;cursor:pointer}.et-common-toggle[disabled],.et-common-toggle[disabled] *{cursor:not-allowed}.et-common-toggle__label{color:inherit;font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;font-size:12px;font-weight:700;text-align:center;text-transform:uppercase;display:table-cell;vertical-align:middle;min-width:30px;height:20px;position:relative}.et-common-toggle__label--on{padding-right:2.5px}.et-common-toggle__label--off{padding-left:2.5px}.et-common-toggle__text{-webkit-transform:translateY(2px);transform:translateY(2px);margin-top:-3px;line-height:1.6em}.et-common-toggle__handle{position:relative;background:#fff;width:100%;height:20px;border-radius:3px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1);-webkit-transition:all 200ms ease;transition:all 200ms ease;position:absolute;top:0;right:0}.et-common-toggle--on{background:#2B87DA;color:#fff}.et-common-toggle--on>.et-common-toggle__label--on>.et-common-toggle__handle{opacity:0;-webkit-transform:translateX(90%);transform:translateX(90%);-webkit-box-shadow:none;box-shadow:none}.et-common-toggle--on>.et-common-toggle__label--off{color:transparent}.et-common-toggle--off>.et-common-toggle__label--off>.et-common-toggle__handle{opacity:0;-webkit-transform:translateX(-90%);transform:translateX(-90%);-webkit-box-shadow:none;box-shadow:none}.et-common-toggle--off>.et-common-toggle__label--on{color:transparent}.et-common-toggle__cursor_default{cursor:default} .et-common-categories>label{font-size:14px;font-weight:600;line-height:20px;margin-bottom:10px;color:#32373C;display:block;max-width:100%}@media (max-width: 749px){.et-common-checkboxes-category-wrap{-webkit-columns:2;-moz-columns:2;columns:2}}.et-common-checkboxes-category-wrap p{padding-bottom:0;margin-top:0 !important;margin-bottom:6px !important;padding-left:34px}.et-common-checkboxes-category-wrap p label{font-size:13px;font-weight:600;position:relative;color:#4C5866;line-height:27.2px;cursor:pointer;text-transform:capitalize}.rtl .et-common-checkboxes-category-wrap p label{padding-right:40px}.et-common-checkboxes-category-wrap p.et-tb-prompt-input-error input[type="checkbox"],.et-common-checkboxes-category-wrap p.et-tb-prompt-input-error input[type="checkbox"]:focus{color:#FF9232;-webkit-box-shadow:inset 0px 0px 0px 2px #FF9232;box-shadow:inset 0px 0px 0px 2px #FF9232;background:rgba(255,146,50,0.1)}.et-common-checkboxes-category-wrap input{margin-bottom:10px;display:block;margin-bottom:10px;display:block;-webkit-appearance:none;-webkit-font-smoothing:subpixel-antialiased;-moz-osx-font-smoothing:grayscale;outline:0;position:absolute;top:-3px;left:-34px;display:inline-block;background:#f1f5f9;width:25px;min-width:16px;height:25px;border:0;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;margin:0;padding:0 !important;float:none;clear:none;color:#4C5866;font-size:13px;font-weight:600;line-height:0;text-align:center;vertical-align:middle;cursor:pointer;margin-top:0 !important}.et-common-checkboxes-category-wrap input:checked:before{content:'\F147';display:inline-block;width:16px;margin:2px 0 0 -5px;float:none;color:#29C4A9;font:normal 21px/1 dashicons;vertical-align:middle;speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.et-common-checkboxes-category-wrap input:checked:after{display:none}.rtl .et-common-checkboxes-category-wrap input{right:0;position:absolute;left:auto}@media (max-width: 749px){.et-cloud-app-status-on .et-common-checkboxes-category-wrap{-webkit-columns:1;-moz-columns:1;columns:1}} .ReactTags__tags{position:relative;z-index:9}.ReactTags__tagInput{background:none;border:none;border-radius:3px;display:inline-block;max-width:100%;min-width:48px;width:1px;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;line-height:24px}.ReactTags__tagInput .ReactTags__tagInputField,.ReactTags__tagInput .ReactTags__tagInputField:focus{min-height:24px;height:24px;margin:0;font-size:13px;font-weight:600;color:#4C5866;width:100%;padding:3px;background:none;border:none}.ReactTags__selected{display:-webkit-box;display:-ms-flexbox;display:flex;border-radius:3px;background:#f1f5f9;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:3px}.ReactTags__selected .ReactTags__tag{border-radius:3px;background:#e0e5ea;display:-webkit-box;display:-ms-flexbox;display:flex;padding:3px 6px 3px 8px;margin:0;color:#7b8490;line-height:18px;margin:2px 4px 2px 0;text-transform:capitalize;font-weight:600}.ReactTags__selected .ReactTags__remove{margin-left:6px !important;cursor:pointer;font-size:18px;color:#7b8490;border:none !important;height:18px !important;width:10px;line-height:19px;font-weight:900;display:inline-block;position:relative;background:none}.ReactTags__suggestions{position:absolute;left:0;width:100%}.ReactTags__suggestions ul{list-style-type:none;background:#fff;width:100%;position:relative;display:block;padding:3px !important;margin:0;margin-top:3px;-webkit-box-shadow:0 5px 30px rgba(43,135,218,0.2);box-shadow:0 5px 30px rgba(43,135,218,0.2);border-bottom-left-radius:3px;border-bottom-right-radius:3px}.ReactTags__suggestions ul li{display:inline-block;margin-bottom:0}.ReactTags__suggestions ul li.ReactTags__activeSuggestion{cursor:pointer}.ReactTags__suggestions ul li mark{background:none;font-weight:600}.ReactTags__suggestions ul li .et-common-tag-suggestion{display:inline-block;border-radius:3px;background:#e0e5ea;padding:3px 6px 3px 8px;margin:2px 4px 2px 0;color:#7b8490;line-height:18px;font-weight:600} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.et-fb-icon{display:inline-block;vertical-align:middle;-webkit-transition:fill 200ms ease;transition:fill 200ms ease}.et-fb-icon svg{display:block;width:100%;fill:inherit}.et-fb-icon svg path.opacity-half{opacity:0.5}.et-fb-icon--loading svg{-webkit-transform-origin:center;transform-origin:center;-webkit-animation:icon-loading-rotate 1s infinite linear;animation:icon-loading-rotate 1s infinite linear;fill:rgba(255,255,255,0.8)}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child{top:50%;left:50%;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%)}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child:before,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child:after{position:absolute;display:block;background:#fff;width:6px;height:6px;border-radius:10px}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child:before,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child:after{content:''}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child:before{left:-11px;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child:after{right:-11px;-webkit-transform:translateX(50%);transform:translateX(50%)}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--animate>.et-fb-icon__child{-webkit-transition:background 0.3s ease;transition:background 0.3s ease}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--animate:before,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--animate:after{-webkit-transition:right 100ms ease,left 100ms ease;transition:right 100ms ease,left 100ms ease}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--animate.et-fb-icon__child--active{-webkit-transition:background 200ms ease;transition:background 200ms ease}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--animate.et-fb-icon__child--active:before,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--animate.et-fb-icon__child--active:after{-webkit-transition:width 100ms 100ms ease,-webkit-transform 100ms 200ms cubic-bezier(0.28, 0.55, 0.385, 1.65);transition:width 100ms 100ms ease,-webkit-transform 100ms 200ms cubic-bezier(0.28, 0.55, 0.385, 1.65);transition:width 100ms 100ms ease,transform 100ms 200ms cubic-bezier(0.28, 0.55, 0.385, 1.65);transition:width 100ms 100ms ease,transform 100ms 200ms cubic-bezier(0.28, 0.55, 0.385, 1.65),-webkit-transform 100ms 200ms cubic-bezier(0.28, 0.55, 0.385, 1.65)}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active{background:transparent;-webkit-transition:background 200ms ease;transition:background 200ms ease}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active:before,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active:after{height:3px}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active:before,.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active:after{width:20px;-webkit-transform-origin:50% 50%;transform-origin:50% 50%}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active:before{left:50%;-webkit-transform:translateX(-50%) rotate(45deg);transform:translateX(-50%) rotate(45deg)}.et-fb-icon--page-settings-main-buttons>.et-fb-icon__child--active:after{right:50%;-webkit-transform:translateX(50%) rotate(-45deg);transform:translateX(50%) rotate(-45deg)}@-webkit-keyframes icon-loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes icon-loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}} .et-common-library-cloud .et-cloud-app__upsell{margin-top:40px}.et-cloud-app__upsell{border-radius:7px;background-color:#f1f5f9;margin-top:20px;padding:20px;text-align:center;-webkit-animation:2s fadeIn;animation:2s fadeIn;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;visibility:hidden}.et-cloud-app__upsell.card-default a{background-color:#2B87DA}.et-cloud-app__upsell.card-free a{background-color:#29C4A9}.et-cloud-app__upsell.card-paid a{background-color:#FF9232}.et-cloud-app__upsell.card-save-modal{border-radius:3px;padding:2px 12px 16px;text-align:left;margin:0 auto 10px;-webkit-animation-duration:5ms;animation-duration:5ms}.et-cloud-app__upsell.card-save-modal a{display:inline;font-weight:700}.et-cloud-app__upsell.card-default.card-save-modal{background-color:rgba(43,135,218,0.1)}.et-cloud-app__upsell.card-free.card-save-modal{background-color:rgba(43,196,169,0.1)}.et-cloud-app__upsell.card-save-modal .et-cloud-app__upsell-description{margin:0 !important;padding-bottom:15px !important}.et-cloud-app__upsell.card-default.card-save-modal .et-cloud-app__upsell-description{color:#2B87DA !important}.et-cloud-app__upsell.card-free.card-save-modal .et-cloud-app__upsell-description{color:#29C4A9 !important}.et-cloud-app__upsell-title{color:#4C5866;font-size:17px;font-weight:700;line-height:24px;margin:0;padding:0;text-transform:capitalize}.et-cloud-app__upsell-description{color:#4C5866 !important;font-size:13px;line-height:18px;margin:0;padding:10px 0 20px !important}.et-cloud-app__upsell a{color:#fff !important;border-radius:3px;display:block;padding:5px 12px;font-size:14px;font-weight:600;line-height:23px;margin:0 auto;text-decoration:none}.et-cloud-app__upsell a:hover{color:#fff}@-webkit-keyframes fadeIn{99%{visibility:hidden}100%{visibility:visible}}@keyframes fadeIn{99%{visibility:hidden}100%{visibility:visible}} .et-core-control-select{background:#f1f5f9;width:100%;border:0;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;margin:0;padding:5px 10px;color:#4C5866;font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;font-size:13px;font-weight:600;height:30px;display:inline-block}body.gecko .et-core-control-select{-moz-appearance:none;z-index:10;background:#f1f5f9 !important;position:relative;border-radius:3px !important}body.gecko .et-core-control-select:after{font-family:'ETmodules' !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;content:'C';position:absolute;right:7px;top:8px;cursor:default;z-index:5}.et-core-control-select:-moz-focusring{text-shadow:0 0 0 #000;color:transparent}.et-core-control-select[disabled]{cursor:not-allowed} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.et-save-to-library-modal{font-family:"Open Sans",Helvetica,Roboto,Arial,sans-serif;font-weight:600;-webkit-font-smoothing:antialiased;font-size:13px}.et-save-to-library-modal .et-save-to-library-description{font-size:13px}.et-save-to-library-modal .et-common-prompt .et-common-prompt__modal .et-common-prompt__container .et-common-button{background:transparent}.et-save-to-library-modal .et-common-prompt .et-common-prompt__modal .et-common-prompt__container .et-common-button--primary{background:#2B87DA;color:#fff}.et-save-to-library-modal .et-common-prompt .et-common-prompt__modal .et-common-prompt__container .et-common-button--cancel{background:#ED5759;color:#fff}.et-save-to-library-modal .et-save-to-library-option input{color:#4C5866}.et-save-to-library-modal .et-save-to-library-option input:focus{outline:none;-webkit-box-shadow:none;box-shadow:none}.et-save-to-library-modal .et-save-to-library-option input[type=checkbox]:checked:after{display:none}.et-save-to-library-modal .et-save-to-library-option--select-cloud-folders{font-size:13px;background-color:#F1F5F9}.et-save-to-library-modal .et-save-to-library-option--select-cloud-folders,.et-save-to-library-modal .et-save-to-library-option--select-cloud-folders:focus,.et-save-to-library-modal .et-save-to-library-option--select-cloud-folders:hover{color:#4C5866}.et-save-to-library-modal .et-save-to-library-option--select-cloud-folders:focus{-webkit-box-shadow:none;box-shadow:none}.et-save-to-library-modal .et-save-to-library-option{padding:10px 0}.et-save-to-library-modal .et-save-to-library-option--hidden{display:none}.et-save-to-library-modal .et-save-to-library-option--label{color:#32373C;font-size:14px;font-weight:600;margin-bottom:5px;display:block}.et-save-to-library-modal .et-save-to-library-option--input{width:100%}.et-save-to-library-modal .et-common-input-text.et-save-to-library-option--input-error{-webkit-box-shadow:inset 0px 0px 0px 2px #FF9232;box-shadow:inset 0px 0px 0px 2px #FF9232;background:rgba(255,146,50,0.1)}.et-save-to-library-modal .et-common-prompt__content{overflow-x:hidden}.et-save-to-library-modal .et-common-prompt__content::-webkit-scrollbar{width:10px;cursor:initial}.et-save-to-library-modal .et-common-prompt__content::-webkit-scrollbar-thumb{background:#4C5866 !important;border-radius:3px;border-right:3px solid #fff;border-left:3px solid #fff}.et-save-to-library-modal .et-common-prompt__content::-webkit-scrollbar-thumb{border-right-width:0;border-radius:0}.rtl .et-save-to-library-modal .et-common-prompt__content::-webkit-scrollbar-thumb{border-left-width:0;border-right-width:3px}.et-save-to-library-modal .et-cloud-category-mark,.et-save-to-library-modal .et-cloud-tag-mark{margin-right:5px !important;margin-left:0px !important;width:14px !important;height:14px !important;min-width:12px !important}.rtl .et-save-to-library-modal .et-cloud-category-mark,.rtl .et-save-to-library-modal .et-cloud-tag-mark{margin-right:0 !important;margin-left:5px !important}.et-save-to-library-modal .et-common-tag-marked,.et-save-to-library-modal .et-common-selected-tag-marked{position:relative;background:#0088E1 !important;color:#fff !important}.et-save-to-library-modal .et-common-tag-marked .ReactTags__remove,.et-save-to-library-modal .et-common-selected-tag-marked .ReactTags__remove{background:#0088E1 !important;color:#fff !important}.et-save-to-library-modal .et-common-tag-marked:before,.et-save-to-library-modal .et-common-selected-tag-marked:before{font-family:'CloudApp';content:'\e900';color:#fff;margin-right:5px} .CodeMirror{font-family:monospace;height:300px;color:black;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:white}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:black}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0 !important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor .CodeMirror-line::-moz-selection, .cm-fat-cursor .CodeMirror-line>span::-moz-selection, .cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:transparent}.cm-fat-cursor .CodeMirror-line::selection,.cm-fat-cursor .CodeMirror-line>span::selection,.cm-fat-cursor .CodeMirror-line>span>span::selection{background:transparent}.cm-fat-cursor .CodeMirror-line::-moz-selection,.cm-fat-cursor .CodeMirror-line>span::-moz-selection,.cm-fat-cursor .CodeMirror-line>span>span::-moz-selection{background:transparent}.cm-fat-cursor{caret-color:transparent}@-webkit-keyframes blink{0%{}50%{background-color:transparent}100%{}}@keyframes blink{0%{}50%{background-color:transparent}100%{}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:#f00}.cm-invalidchar{color:#f00}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,0.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:white}.CodeMirror-scroll{overflow:scroll !important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative;z-index:0}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none !important;border:none !important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:0.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-webkit-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::-moz-selection, .CodeMirror-line>span::-moz-selection, .CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,0.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:none} .CodeMirror-hints{position:absolute;z-index:10;overflow:hidden;list-style:none;margin:0;padding:2px;-webkit-box-shadow:2px 3px 5px rgba(0,0,0,0.2);box-shadow:2px 3px 5px rgba(0,0,0,0.2);border-radius:3px;border:1px solid silver;background:white;font-size:90%;font-family:monospace;max-height:20em;overflow-y:auto}.CodeMirror-hint{margin:0;padding:0 4px;border-radius:2px;white-space:pre;color:black;cursor:pointer}li.CodeMirror-hint-active{background:#08f;color:white} .CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.CodeMirror-dialog button{font-size:70%} .codemirror-colorview{border:1px solid #8e8e8e;position:relative;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0px 2px;width:10px;height:10px;cursor:pointer;background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC");background-repeat:repeat}.codemirror-colorview .codemirror-colorview-background{content:"";position:absolute;left:0px;right:0px;bottom:0px;top:0px}.codemirror-colorview:hover{border-color:#494949}.codemirror-colorpicker{position:relative;width:224px;z-index:1000;border:1px solid black}.codemirror-colorpicker>.color{position:relative;height:120px;overflow:hidden;cursor:pointer}.codemirror-colorpicker>.color>.saturation{position:relative;width:100%;height:100%}.codemirror-colorpicker>.color>.saturation>.value{position:relative;width:100%;height:100%}.codemirror-colorpicker>.color>.saturation>.value>.drag-pointer{position:absolute;width:10px;height:10px;border-radius:50%;left:-5px;top:-5px}.codemirror-colorpicker>.control{position:relative;padding:10px 0px 10px 0px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.codemirror-colorpicker>.control>.color,.codemirror-colorpicker>.control>.empty{position:absolute;left:11px;top:14px;width:30px;height:30px;border-radius:50%;-webkit-box-sizing:border-box;box-sizing:border-box}.codemirror-colorpicker>.control>.hue{position:relative;padding:6px 16px;margin:0px 0px 0px 45px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.codemirror-colorpicker>.control>.hue>.hue-container{position:relative;width:100%;height:10px;border-radius:3px}.codemirror-colorpicker>.control>.opacity{position:relative;padding:3px 16px;margin:0px 0px 0px 45px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.codemirror-colorpicker>.control>.opacity>.opacity-container{position:relative;width:100%;height:10px;border-radius:3px}.codemirror-colorpicker>.control .drag-bar,.codemirror-colorpicker>.control .drag-bar2{position:absolute;cursor:pointer;top:50% !important;margin-top:-7px !important;left:-3px;width:12px;height:12px;border-radius:50px}.codemirror-colorpicker>.information{position:relative;-webkit-box-sizing:padding-box;box-sizing:padding-box}.codemirror-colorpicker>.information.hex>.information-item.hex{display:-webkit-box;display:-ms-flexbox;display:flex}.codemirror-colorpicker>.information.rgb>.information-item.rgb{display:-webkit-box;display:-ms-flexbox;display:flex}.codemirror-colorpicker>.information.hsl>.information-item.hsl{display:-webkit-box;display:-ms-flexbox;display:flex}.codemirror-colorpicker>.information>.information-item{display:none;position:relative;padding:0px 5px;-webkit-box-sizing:border-box;box-sizing:border-box;margin-right:40px}.codemirror-colorpicker>.information>.information-change{position:absolute;display:block;width:40px;top:0px;right:0px;bottom:0px}.codemirror-colorpicker>.information>.information-change>.format-change-button{width:100%;height:100%;background:transparent;border:0px;cursor:pointer;outline:none}.codemirror-colorpicker>.information>.information-item>.input-field{display:block;-webkit-box-flex:1;-ms-flex:1;flex:1;padding:3px;-webkit-box-sizing:border-box;box-sizing:border-box}.codemirror-colorpicker>.information>.information-item>.input-field>input{text-align:center;width:100%;padding:3px;font-size:11px;color:#333;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text;user-select:text;border:1px solid #cbcbcb;border-radius:2px}.codemirror-colorpicker>.information>.information-item>.input-field>.title{text-align:center;font-size:12px;color:#a9a9a9;padding-top:2px}.codemirror-colorpicker>.information>input{position:absolute;font-size:10px;height:20px;bottom:20px;padding:0 0 0 2px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;-o-user-select:text;user-select:text}.codemirror-colorpicker{border:1px solid rgba(0,0,0,0.2);background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0px 10px 0px rgba(0,0,0,0.12);box-shadow:0 0px 10px 0px rgba(0,0,0,0.12)}.codemirror-colorpicker>.color>.saturation{background-color:rgba(204,154,129,0);background-image:-webkit-gradient(linear, left top, right top, from(#fff), to(rgba(204,154,129,0)));background-image:linear-gradient(to right, #fff, rgba(204,154,129,0));background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#00cc9a81', GradientType=1)}.codemirror-colorpicker>.color>.saturation>.value{background-image:-webkit-gradient(linear, left bottom, left top, from(#000), to(rgba(204,154,129,0)));background-image:linear-gradient(to top, #000, rgba(204,154,129,0))}.codemirror-colorpicker>.color>.saturation>.value>.drag-pointer{border:1px solid #fff;-webkit-box-shadow:0 0 2px 0 rgba(0,0,0,0.05);box-shadow:0 0 2px 0 rgba(0,0,0,0.05)}.codemirror-colorpicker>.control>.hue>.hue-container{background:-webkit-gradient(linear, left top, right top, from(red), color-stop(17%, #ff0), color-stop(33%, lime), color-stop(50%, cyan), color-stop(67%, blue), color-stop(83%, #f0f), to(red));background:linear-gradient(to right, red 0%, #ff0 17%, lime 33%, cyan 50%, blue 67%, #f0f 83%, red 100%)}.codemirror-colorpicker>.control>.opacity>.opacity-container>.color-bar{position:absolute;display:block;content:"";left:0px;right:0px;bottom:0px;top:0px;background:-webkit-gradient(linear, left top, right top, from(rgba(232,232,232,0)), to(#e8e8e8));background:linear-gradient(to right, rgba(232,232,232,0), #e8e8e8)}.codemirror-colorpicker>.control>.opacity>.opacity-container{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC");background-repeat:repeat}.codemirror-colorpicker>.control>.empty{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC") repeat}.codemirror-colorpicker>.control .drag-bar,.codemirror-colorpicker>.control .drag-bar2{border:1px solid rgba(0,0,0,0.05);-webkit-box-shadow:0 0 2px 0 rgba(0,0,0,0.1);box-shadow:2px 2px 2px 0px rgba(0,0,0,0.2);background-color:#fefefe}.codemirror-colorpicker>.information>.title{color:#a3a3a3}.codemirror-colorpicker>.information>.input{color:#333}.codemirror-colorpicker>.colorsets{border-top:1px solid #e2e2e2}.codemirror-colorpicker>.colorsets>.menu{float:right;padding:4px 6px}.codemirror-colorpicker>.colorsets>.menu button{border:0px;font-size:14px;font-weight:300;font-family:serif, sans-serif;outline:none;cursor:pointer}.codemirror-colorpicker>.colorsets>.color-list{margin-right:20px;display:block;padding:12px;padding-bottom:0px;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:0}.codemirror-colorpicker>.colorsets>.color-list .color-item{width:13px;height:13px;border-radius:3px;display:inline-block;margin-right:12px;margin-bottom:12px;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQYV2NctWrVfwYkEBYWxojMZ6SDAmT7QGx0K1EcRBsFAADeG/3M/HteAAAAAElFTkSuQmCC") no-repeat;background-size:contain;border:1px solid rgba(221,221,221,0.5);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer;vertical-align:middle}.codemirror-colorpicker>.colorsets>.color-list .color-item:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.codemirror-colorpicker>.colorsets>.color-list .color-item .color-view{width:100%;height:100%;padding:0px;margin:0px;pointer-events:none}.codemirror-colorpicker>.colorsets>.color-list .add-color-item{display:inline-block;margin-bottom:12px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer;line-height:0;font-size:16px;font-weight:400;font-family:serif,sans-serif;color:#8e8e8e;vertical-align:middle}.codemirror-colorpicker>.color-chooser{position:absolute;top:0px;left:0px;right:0px;bottom:0px;background-color:rgba(0,0,0,0.3)}.codemirror-colorpicker>.color-chooser>.colorsets-list{position:absolute;top:120px;left:0px;right:0px;bottom:0px;background-color:white} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}html{}.et-common-codemirror{position:relative}.et-common-codemirror textarea.et-fb-settings-option-textarea,.et-common-codemirror textarea.et-fb-settings-option-textarea:focus{background-color:#4C5866 !important}.et-common-codemirror .react-codemirror2{border-radius:3px;background-color:#4C5866;min-height:120px;overflow:hidden}.et-common-codemirror .react-codemirror2 .CodeMirror-widget{line-height:8px}.et-common-codemirror .react-codemirror2 .CodeMirror-wrap{padding:4px 6px 4px 0}.et-common-codemirror .react-codemirror2 .CodeMirror-sizer{margin-left:29px !important}.et-common-codemirror .react-codemirror2 .CodeMirror-gutter-wrapper{left:-29px !important}.et-common-codemirror .react-codemirror2 .CodeMirror-gutters{left:-29px !important}.et-common-codemirror .react-codemirror2 .CodeMirror-gutters .CodeMirror-linenumbers{width:29px !important}.et-common-codemirror .react-codemirror2 .CodeMirror-linenumber.CodeMirror-gutter-elt{width:21px !important}.et-common-codemirror .react-codemirror2 .CodeMirror{font-size:13px;line-height:150%;height:auto}.et-common-codemirror .react-codemirror2 .CodeMirror .CodeMirror-scroll{min-height:110px;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;outline:none}.et-common-codemirror .react-codemirror2 .CodeMirror .CodeMirror-linenumber{text-align:right}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et{background-color:#4C5866;color:#fff}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-placeholder{color:#A2B0C1}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-gutters{background:#4C5866;color:#537f7e;border:none}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-guttermarker,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-guttermarker-subtle,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-linenumber{color:#8393a5}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-cursor{border-left:1px solid #fff}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et div.CodeMirror-selected{background:rgba(145,203,255,0.2)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-s-material.CodeMirror-focused div.CodeMirror-selected{background:rgba(0,0,0,0.1)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line::-moz-selection, .et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line>span::-moz-selection, .et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line>span>span::-moz-selection{background:rgba(0,0,0,0.1)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line::selection,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line>span::selection,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line>span>span::selection{background:rgba(0,0,0,0.1)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line::-moz-selection,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line>span::-moz-selection,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-line>span>span::-moz-selection{background:rgba(0,0,0,0.1)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-activeline-background{background:rgba(0,0,0,0.1)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et.CodeMirror-empty .CodeMirror-activeline-background{background:#4C5866}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et.CodeMirror-empty.CodeMirror-focused .CodeMirror-activeline-background{background:rgba(0,0,0,0.1)}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et.CodeMirror-empty .CodeMirror-scroll{min-height:120px;margin-bottom:-20px}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-keyword{color:#88c2f8}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-operator{color:#fff}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-variable-2,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-string-2,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-meta{color:#fff}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-variable-3,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-type{color:#88c2f8}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-builtin,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-qualifier,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-variable-3,.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-type{color:#fe9c47}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-atom{color:#88c2f8}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-number{color:#fe9c47}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-def{color:#fff}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-string{color:#fe9c47}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-comment{color:#8393a5}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-variable{color:#88c2f8}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-attribute{color:#88c2f8}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-property{color:#88dfbe}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-tag{color:#88dfbe}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .cm-searching{background:none;border-bottom:1px solid #fff;color:#fff}.et-common-codemirror .react-codemirror2 .CodeMirror.cm-s-et .CodeMirror-matchingbracket{text-decoration:underline;color:#fff !important}.et-common-codemirror .react-codemirror2 .CodeMirror .CodeMirror-matchingtag{background:rgba(255,255,255,0.15)}.et-common-codemirror .react-codemirror2 .CodeMirror .CodeMirror-linewidget{width:100% !important}.et-common-codemirror .react-codemirror2 .CodeMirror .codemirror-lint-warning,.et-common-codemirror .react-codemirror2 .CodeMirror .codemirror-lint-error{background-color:transparent;border-radius:3px;padding:5px 10px;margin:5px 0}.et-common-codemirror .react-codemirror2 .CodeMirror .codemirror-lint-error{color:#ff5758;border:2px solid #ff5758}.et-common-codemirror .react-codemirror2 .CodeMirror .codemirror-lint-warning{color:#fe9c47;border:2px solid #fe9c47}.et-common-codemirror .react-codemirror2 .CodeMirror .codemirror-colorview{border:1px solid #fff;border-radius:10px;margin:0 5px 0 0}.et-common-codemirror .react-codemirror2 .CodeMirror .codemirror-colorview .codemirror-colorview-background{border-radius:10px}.et-cloud-app-details-view-active .et-common-codemirror .react-codemirror2 .CodeMirror{font-weight:normal;height:100%}.et-common-codemirror textarea.et-fb-settings-option-textarea{display:block;resize:none}.et-cloud-app-codemirror .et-common-codemirror,.et-cloud-app-codemirror .et-common-codemirror .react-codemirror2,.et-common-codemirror .et-cloud-app-codemirror .CodeMirror{height:100%}.CodeMirror-vscrollbar::-webkit-scrollbar{width:10px;cursor:initial}.CodeMirror-vscrollbar::-webkit-scrollbar-thumb{background:#67737F !important;border-radius:3px;border-right:3px solid #4C5866;border-left:3px solid #4C5866}#et-cloud-app .et-cloud-app-layout-screenshot.et-cloud-app-codemirror .et-cloud-app-layout-cta-buttons{margin-top:-40px}#et-cloud-app .et-cloud-app-layout-screenshot.et-cloud-app-codemirror .et-cloud-app-layout-cta-buttons .et-common-button{z-index:9}html .CodeMirror-hints{z-index:1000000000}html .codemirror-colorpicker{z-index:1000000000}html .CodeMirror-dialog-top{background:#F1F5F9;border-bottom:none;-webkit-box-shadow:0 0 50px rgba(0,0,0,0.5);box-shadow:0 0 50px rgba(0,0,0,0.5);height:30px}html .CodeMirror-dialog-top .CodeMirror-search-label{color:#bec9d6;font-size:14px;font-weight:600;height:30px}html .CodeMirror-dialog-top .CodeMirror-search-field{font-weight:600 !important;color:#4C5866 !important;font-size:13px !important;height:30px}html .CodeMirror-dialog-top .CodeMirror-search-hint{display:none} @-webkit-keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@keyframes et-spinner{0%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}25%{-webkit-box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9;box-shadow:17px 0 #2B87DA,0 17px #29C4A9,-17px 0 #2B87DA,0 -17px #29C4A9}50%{-webkit-box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232;box-shadow:0 17px #2B87DA,-17px 0 #FF9232,0 -17px #2B87DA,17px 0 #FF9232}75%{-webkit-box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232;box-shadow:-17px 0 #7E3BD0,0 -17px #FF9232,17px 0 #7E3BD0,0 17px #FF9232}100%{-webkit-box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9;box-shadow:0 -17px #7E3BD0,17px 0 #29C4A9,0 17px #7E3BD0,-17px 0 #29C4A9}}@-webkit-keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}@keyframes et-pulse-animation{0%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}10%{-webkit-transform:scale(1);transform:scale(1)}20%{-webkit-transform:scale(1.02);transform:scale(1.02)}30%{-webkit-transform:scale(1.04);transform:scale(1.04)}40%{-webkit-transform:scale(1.06);transform:scale(1.06)}50%{-webkit-transform:scale(1.08);transform:scale(1.08)}60%{-webkit-transform:scale(1.06);transform:scale(1.06);border-color:#00c3aa}70%{-webkit-transform:scale(1.04);transform:scale(1.04)}80%{-webkit-transform:scale(1.02);transform:scale(1.02)}80%{-webkit-transform:scale(1);transform:scale(1)}100%{-webkit-transform:scale(0.95);transform:scale(0.95);border-color:#2b87da}}.divi-cloud-item-editor-overlay{position:fixed;left:0;top:0;width:100vw;height:100vh;background:radial-gradient(ellipse at center, #fff 20%, rgba(255,255,255,0.7) 100%);z-index:159900;-webkit-animation:et-core-fade-in 500ms linear;animation:et-core-fade-in 500ms linear}.divi-cloud-item-editor-modal-positioner{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;position:fixed;left:30px;top:32px;right:30px;bottom:30px;z-index:159900;-webkit-font-smoothing:antialiased}.divi-cloud-item-editor .et-common-prompt__container{width:calc(100% - 40px);height:calc(100% - 40px)}.divi-cloud-item-editor .et-common-prompt__body{height:calc(100vh - 140px)}.divi-cloud-item-editor .et-common-prompt .react-codemirror2 .CodeMirror{height:calc(100vh - 210px)}.et-fb .divi-cloud-item-editor .et-common-prompt .react-codemirror2 .CodeMirror{height:calc(100vh - 202px)} #et-code-snippets-container{position:relative;z-index:9999999}.et-code-snippets-library__container #et-cloud-app .et-cloud-app-layout .et-cloud-app-meta-icons{margin-top:15px}.et-code-snippets-library__container #et-cloud-app .et-cloud-app-layout-placeholder:before{font-family:'etbuilder';speak:none;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:80px;margin-bottom:5px;color:#e7eef5;content:'\0074';z-index:99;position:absolute;top:0;right:0;width:100%;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.et-code-snippets-library__container #et-cloud-app .et-cloud-app-layout-screenshot::before{position:static !important}.et-code-snippets-library__container #et-cloud-app .et-cloud-app-layouts-grid-item-disabled .et-cloud-app-layout-placeholder:before{content:''} PKE\K\build/.htaccessnu[ RewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] PKE\p̼kbuild/et-core-app.bundle.jsnu[/*! This minified app bundle contains open source software from several third party developers. Please review CREDITS.md in the root directory or LICENSE.md in the current directory for complete licensing, copyright and patent information. This file and the included code may not be redistributed without the attributions listed in LICENSE.md, including associate copyright notices and licensing information. */!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="http://0.0.0.0:31499/",n(n.s=226)}([function(e,t){e.exports=React},function(e,t,n){e.exports=n(274)()},function(e,t,n){"use strict";n.r(t),n.d(t,"props",(function(){return Y})),n.d(t,"path",(function(){return G})),n.d(t,"state",(function(){return $})),n.d(t,"string",(function(){return K})),n.d(t,"sequences",(function(){return Z})),n.d(t,"computed",(function(){return X})),n.d(t,"moduleState",(function(){return Q})),n.d(t,"moduleSequences",(function(){return J})),n.d(t,"moduleComputed",(function(){return ee})),n.d(t,"ModuleClass",(function(){return h})),n.d(t,"ControllerClass",(function(){return j})),n.d(t,"ProviderClass",(function(){return g.a})),n.d(t,"BaseControllerClass",(function(){return k})),n.d(t,"ChainSequenceFactory",(function(){return z})),n.d(t,"ChainSequenceWithPropsFactory",(function(){return F})),n.d(t,"sequence",(function(){return s.j})),n.d(t,"parallel",(function(){return s.h})),n.d(t,"createTemplateTag",(function(){return s.e})),n.d(t,"extractValueWithPath",(function(){return s.g})),n.d(t,"resolveObject",(function(){return s.i})),n.d(t,"ResolveValue",(function(){return s.c})),n.d(t,"Tag",(function(){return s.d})),n.d(t,"Controller",(function(){return te})),n.d(t,"UniversalController",(function(){return ne})),n.d(t,"UniversalApp",(function(){return re})),n.d(t,"Module",(function(){return oe})),n.d(t,"CerebralError",(function(){return U})),n.d(t,"Provider",(function(){return g.a})),n.d(t,"Compute",(function(){return u.c})),n.d(t,"Reaction",(function(){return d})),n.d(t,"View",(function(){return V})),n.d(t,"createDummyController",(function(){return o.d})),n.d(t,"throwError",(function(){return o.y})),n.d(t,"default",(function(){return ae}));var r=n(43),o=n(5),i=function(){function e(e,t){for(var n=0;nt.rawId?1:-1}))}},{key:"getUniqueEntities",value:function(e){return Object(o.g)(e,this.map).reduce((function(e,t){return(t.entities||[]).reduce((function(e,t){return-1===e.indexOf(t)?e.concat(t):e}),e)}),[]).sort((function(e,t){return e.rawId>t.rawId?1:-1}))}}]),e}(),s=n(12),u=n(20),l=n(53),c=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:[];n=Object(o.h)(n),Object(o.a)("module.*","use the new STORE provider, store.set(state.isAwesome, true)");for(var r=this.context.execution.name.split("."),i=r.splice(0,r.length-1),a=arguments.length,s=Array(a>1?a-1:0),u=1;u2&&void 0!==arguments[2]?arguments[2]:{};!this.devtools||Object(o.v)(r)&&Object(o.w)(r)||(console.warn('You passed an invalid payload to sequence "'+e+'". Only serializable payloads can be passed to a sequence. The payload has been ignored. This is the object:',r),r={}),this.devtools&&(r=Object.keys(r).reduce((function(t,i){return Object(o.w)(r[i],n.devtools.allowedTypes)?(t[i]=Object(o.k)(r[i]),t):(console.warn('You passed an invalid payload to sequence "'+e+'", on key "'+i+'". Only serializable values like Object, Array, String, Number and Boolean can be passed in. Also these special value types:',n.devtools.allowedTypes),t)}),{}));var i=function(e){if(e){var t=Object(o.h)(e.execution.name).reduce((function(e,t,n){return e.currentModule.catch&&(e.catchingModule=e.currentModule),e.currentModule=e.currentModule.modules[t],e}),{currentModule:n.module,catchingModule:null});if(t.catchingModule){var r=!0,i=!1,a=void 0;try{for(var s,u=t.catchingModule.catch[Symbol.iterator]();!(r=(s=u.next()).done);r=!0){var l=_(s.value,2),c=l[0],f=l[1];if(e instanceof c)return n.runSequence("catch",f,e.payload),void(n.throwToConsole&&setTimeout((function(){console.log('Cerebral is handling error "'+e.name+": "+e.message+'" thrown by sequence "'+e.execution.name+'". Check debugger for more information.')})))}}catch(e){i=!0,a=e}finally{try{!r&&u.return&&u.return()}finally{if(i)throw a}}}if(!n.noRethrow){if(!e.execution.isAsync)throw e;setTimeout((function(){throw e}))}}};if(this.returnSequencePromise)return this.run(e,t,r).catch(i);this.run(e,t,r,i)}},{key:"getSequence",value:function(e){var t=Object(o.h)(e),n=t.pop(),r=t.reduce((function(e,t){return e?e.modules[t]:void 0}),this.module),i=r&&r.sequences[n];if(i)return i&&i.run}},{key:"getSequences",value:function(e){var t=Object(o.h)(e).reduce((function(e,t){return e?e.modules[t]:void 0}),this.module),n=t&&t.sequences;if(n){var r={};for(var i in n)r[i]=n[i].run;return r}}},{key:"addModule",value:function(e,t){var n=Object(o.h)(e),r=n.pop(),i=Object(o.m)(n,this.module),a=t instanceof h?t.create(this,Object(o.h)(e)):new h(t).create(this,Object(o.h)(e));i.modules[r]=a,a.providers&&Object.assign(this.contextProviders,a.providers),this.emit("moduleAdded",e.split("."),a),this.flush()}},{key:"removeModule",value:function(e){var t=this;if(!e)return console.warn("Controller.removeModule requires a Module Path"),null;var n=Object(o.h)(e),r=n.pop(),i=Object(o.m)(n,this.module),a=i.modules[r];a.providers&&Object.keys(a.providers).forEach((function(e){delete t.contextProviders[e]})),delete i.modules[r],this.emit("moduleRemoved",Object(o.h)(e),a),this.flush()}}]),t}(s.f),C=n(90),O="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},E=function(){function e(e,t){for(var n=0;n2&&void 0!==arguments[2]&&arguments[2];e.length?e.reduce((function(i,a,s){if(s===e.length-1){Array.isArray(i)||Object(o.v)(i)||Object(o.y)('The path "'+e.join(".")+'" is invalid. Path: "'+e.slice(0,e.length-1).join(".")+'" is type of "'+(null===i?"null":void 0===i?"undefined":O(i))+'"');var u=i[a];t(i[a],i,a),(i[a]!==u||Object(o.s)(i[a])&&Object(o.s)(u))&&n.changedPaths.push({path:e,forceChildPathUpdates:r})}else i[a]||(i[a]={});return i[a]}),this.state):t(this.state,this,"state")}},{key:"checkForComputed",value:function(e){var t=e.reduce((function(e,t){return e[t]}),this.state);if(t instanceof u.a&&Object(o.y)('You are trying to replace a computed value on path "'+e.join(".")+'", but that is not allowed'),Object(o.v)(t)){!function e(t,n){Object.keys(t).forEach((function(r){t[r]instanceof u.a?Object(o.y)('You are trying to replace a computed value on path "'+n.join(".")+'", but that is not allowed'):Object(o.v)(t[r])&&e(t[r],n.concat(r))}))}(t,e)}}},{key:"verifyValue",value:function(e,t){this.devtools&&(this.checkForComputed(t),Object(o.w)(e,this.devtools.allowedTypes)||Object(o.y)('You are passing a non serializable value into the state tree on path "'+t.join(".")+'"'),Object(o.k)(e),this.devtools.warnStateProps&&Object(o.b)(e))}},{key:"verifyValues",value:function(e,t){var n=this;this.devtools&&e.forEach((function(e){n.verifyValue(e,t)}))}},{key:"emitMutationEvent",value:function(e,t,n){for(var r=arguments.length,o=Array(r>3?r-3:0),i=3;i0&&void 0!==arguments[0]?arguments[0]:[];return e.reduce((function(t,n,r){return t instanceof u.b?t:t instanceof u.a?new u.b(t,e.slice(r)):t?t[n]:void 0}),this.state)}},{key:"set",value:function(e,t){this.verifyValue(t,e),this.updateIn(e,(function(e,n,r){n[r]=t}),!0),this.emitMutationEvent("set",e,!0,t)}},{key:"toggle",value:function(e){this.updateIn(e,(function(e,t,n){t[n]=!e})),this.emitMutationEvent("toggle",e,!1)}},{key:"push",value:function(e,t){this.verifyValue(t,e),this.updateIn(e,(function(e){e.push(t)})),this.emitMutationEvent("push",e,t,!1)}},{key:"merge",value:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r1?t-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:1;if(!Number.isInteger(t))throw new Error("Cerebral state.increment: you must increment with integer values.");this.updateIn(e,(function(e,n,r){if(!Number.isInteger(e))throw new Error("Cerebral state.increment: you must increment integer values.");n[r]=e+t})),this.emitMutationEvent("increment",e,!1,t)}}]),t}(C.a),T=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},n=this.createContext(t),r=e.getValue(n);return Object(o.t)(r)?r.getValue(t):r}},{key:"createContext",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=t.length?t.join(".")+".":"";return{props:e,controller:this,execution:{name:n}}}},{key:"createDependencyMap",value:function(e,t,n){var r=this,i=this.createContext(t,n);return e.reduce((function(e,n){return n instanceof s.d?n.getTags(i).reduce((function(e,n){if("state"===n.type||"moduleState"===n.type){var a=n.getValue(i);if(Object(o.t)(a))return a.getValue(t),Object.assign(e,a.getDependencyMap());var s=n.getPath(i);e[Object(o.i)(s,r.getState(s))]=!0}return e}),e):e}),{})}}]),t}(k),M=function(){function e(e,t){for(var n=0;nwindow.CEREBRAL_STATE = "+e+"<\/script>"}},{key:"runSequence",value:function(e,t){var n=void 0;if(Array.isArray(e))n=this.run("UniversalController.run",e,t);else if("string"==typeof e){var r=Object(o.h)(e),i=r.pop(),a=Object(o.m)(r,this.module),s=a&&a.sequences[i];n=this.run(e,s.sequence,t)}else Object(o.y)("Sequence must be a sequence-path or an array of action.");return n}},{key:"setState",value:function(e,t){this.model.set(Object(o.h)(e),t),this.flush(!0)}}]),t}(j),P=n(46),R=(L=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])},function(e,t){function n(){this.constructor=e}L(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),D=function(){function e(e){this.sequenceArray=e}return e.prototype.action=function(){for(var t=[],n=0;n0&&void 0!==arguments[0]?arguments[0]:"";B(this,t);var n=H(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return Object.defineProperty(n,"message",{configurable:!0,enumerable:!1,value:e,writable:!0}),Object.defineProperty(n,"name",{configurable:!0,enumerable:!1,value:n.constructor.name,writable:!0}),Error.hasOwnProperty("captureStackTrace")?(Error.captureStackTrace(n,n.constructor),H(n)):(Object.defineProperty(n,"stack",{configurable:!0,enumerable:!1,value:new Error(e).stack,writable:!0}),n)}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(function(e){function t(){e.apply(this,arguments)}return t.prototype=Object.create(e.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e,t}(Error))),W=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},r=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],i=Object.keys(this.dependencies).reduce((function(r,i){var a=t.dependencies[i],s=a.getValue(e);if(Object(o.t)(s)){var u=a.getPath(e);t.computedWithProps[u]?r[i]=t.computedWithProps[u].getValue(n):r[i]=s.getValue(n)}else r[i]=s;return r}),{});return this.controller.devtools&&this.controller.devtools.bigComponentsWarning&&!this._hasWarnedBigComponent&&Object.keys(this.dependencies).length>=this.controller.devtools.bigComponentsWarning&&(console.warn("Component named "+this._displayName+" has a lot of dependencies, consider refactoring or adjust this option in devtools"),this._hasWarnedBigComponent=!0),this.mergeProps?this.mergeProps(i,n,(function(t){t instanceof s.d||Object(o.y)("You are not passing a tag to the mergeProp get function");var r=t.getValue(e);return Object(o.t)(r)?r.getValue(n):r})):(i.get=this.createDynamicGetter(n,e),i.reaction=this.createReaction,Object.assign({},r?n:{},i))}},{key:"render",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:function(){},n=arguments[2],r=this.controller.createContext(e),o=this.getProps(r,e,n);this.executedCount++,this.controller.devtools&&this.controller.devtools.sendWatchMap([],[],0,0);var i=t(o);return this.dynamicDependencies.length&&this.update(e),i}}]),t}(l.a),q=r;var Y=q.props,G=q.path,$=q.state,K=q.string,Z=q.sequences,X=q.computed,Q=q.moduleState,J=q.moduleSequences,ee=q.moduleComputed;function te(e,t){return Object(o.a)("Controller","Use App default import instead"),new j(e,t)}function ne(e,t){return Object(o.a)("UniversalController","Use UniversalApp import instead"),new A(e,t)}function re(e,t){return new A(e,t)}function oe(e){return Object(o.a)("Module","Use plain object/function. Type with ModuleDefinition export"),new h(e)}var ie=void 0;function ae(e,t){return t&&!0===t.hotReloading&&ie?(ie.reconfigure(e),ie):ie=new j(e,t)}},function(e,t){e.exports=function(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){(function(e,n){(function(){var r="Expected a function",o="__lodash_placeholder__",i=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],a="[object Arguments]",s="[object Array]",u="[object Boolean]",l="[object Date]",c="[object Error]",f="[object Function]",d="[object GeneratorFunction]",p="[object Map]",h="[object Number]",v="[object Object]",g="[object RegExp]",m="[object Set]",y="[object String]",b="[object Symbol]",w="[object WeakMap]",_="[object ArrayBuffer]",x="[object DataView]",k="[object Float32Array]",C="[object Float64Array]",O="[object Int8Array]",E="[object Int16Array]",S="[object Int32Array]",T="[object Uint8Array]",j="[object Uint16Array]",M="[object Uint32Array]",L=/\b__p \+= '';/g,A=/\b(__p \+=) '' \+/g,P=/(__e\(.*?\)|\b__t\)) \+\n'';/g,R=/&(?:amp|lt|gt|quot|#39);/g,D=/[&<>"']/g,I=RegExp(R.source),N=RegExp(D.source),z=/<%-([\s\S]+?)%>/g,F=/<%([\s\S]+?)%>/g,B=/<%=([\s\S]+?)%>/g,H=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,U=/^\w*$/,W=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,V=/[\\^$.*+?()[\]{}|]/g,q=RegExp(V.source),Y=/^\s+/,G=/\s/,$=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,K=/\{\n\/\* \[wrapped with (.+)\] \*/,Z=/,? & /,X=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Q=/[()=,{}\[\]\/\s]/,J=/\\(\\)?/g,ee=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,te=/\w*$/,ne=/^[-+]0x[0-9a-f]+$/i,re=/^0b[01]+$/i,oe=/^\[object .+?Constructor\]$/,ie=/^0o[0-7]+$/i,ae=/^(?:0|[1-9]\d*)$/,se=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,ue=/($^)/,le=/['\n\r\u2028\u2029\\]/g,ce="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",fe="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",de="[\\ud800-\\udfff]",pe="["+fe+"]",he="["+ce+"]",ve="\\d+",ge="[\\u2700-\\u27bf]",me="[a-z\\xdf-\\xf6\\xf8-\\xff]",ye="[^\\ud800-\\udfff"+fe+ve+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",be="\\ud83c[\\udffb-\\udfff]",we="[^\\ud800-\\udfff]",_e="(?:\\ud83c[\\udde6-\\uddff]){2}",xe="[\\ud800-\\udbff][\\udc00-\\udfff]",ke="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Ce="(?:"+me+"|"+ye+")",Oe="(?:"+ke+"|"+ye+")",Ee="(?:"+he+"|"+be+")"+"?",Se="[\\ufe0e\\ufe0f]?"+Ee+("(?:\\u200d(?:"+[we,_e,xe].join("|")+")[\\ufe0e\\ufe0f]?"+Ee+")*"),Te="(?:"+[ge,_e,xe].join("|")+")"+Se,je="(?:"+[we+he+"?",he,_e,xe,de].join("|")+")",Me=RegExp("['\u2019]","g"),Le=RegExp(he,"g"),Ae=RegExp(be+"(?="+be+")|"+je+Se,"g"),Pe=RegExp([ke+"?"+me+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?="+[pe,ke,"$"].join("|")+")",Oe+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?="+[pe,ke+Ce,"$"].join("|")+")",ke+"?"+Ce+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?",ke+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ve,Te].join("|"),"g"),Re=RegExp("[\\u200d\\ud800-\\udfff"+ce+"\\ufe0e\\ufe0f]"),De=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Ie=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Ne=-1,ze={};ze[k]=ze[C]=ze[O]=ze[E]=ze[S]=ze[T]=ze["[object Uint8ClampedArray]"]=ze[j]=ze[M]=!0,ze[a]=ze[s]=ze[_]=ze[u]=ze[x]=ze[l]=ze[c]=ze[f]=ze[p]=ze[h]=ze[v]=ze[g]=ze[m]=ze[y]=ze[w]=!1;var Fe={};Fe[a]=Fe[s]=Fe[_]=Fe[x]=Fe[u]=Fe[l]=Fe[k]=Fe[C]=Fe[O]=Fe[E]=Fe[S]=Fe[p]=Fe[h]=Fe[v]=Fe[g]=Fe[m]=Fe[y]=Fe[b]=Fe[T]=Fe["[object Uint8ClampedArray]"]=Fe[j]=Fe[M]=!0,Fe[c]=Fe[f]=Fe[w]=!1;var Be={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},He=parseFloat,Ue=parseInt,We="object"==typeof e&&e&&e.Object===Object&&e,Ve="object"==typeof self&&self&&self.Object===Object&&self,qe=We||Ve||Function("return this")(),Ye=t&&!t.nodeType&&t,Ge=Ye&&"object"==typeof n&&n&&!n.nodeType&&n,$e=Ge&&Ge.exports===Ye,Ke=$e&&We.process,Ze=function(){try{var e=Ge&&Ge.require&&Ge.require("util").types;return e||Ke&&Ke.binding&&Ke.binding("util")}catch(e){}}(),Xe=Ze&&Ze.isArrayBuffer,Qe=Ze&&Ze.isDate,Je=Ze&&Ze.isMap,et=Ze&&Ze.isRegExp,tt=Ze&&Ze.isSet,nt=Ze&&Ze.isTypedArray;function rt(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function ot(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o-1}function ct(e,t,n){for(var r=-1,o=null==e?0:e.length;++r-1;);return n}function Pt(e,t){for(var n=e.length;n--&&bt(t,e[n],0)>-1;);return n}function Rt(e,t){for(var n=e.length,r=0;n--;)e[n]===t&&++r;return r}var Dt=Ct({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),It=Ct({"&":"&","<":"<",">":">",'"':""","'":"'"});function Nt(e){return"\\"+Be[e]}function zt(e){return Re.test(e)}function Ft(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}function Bt(e,t){return function(n){return e(t(n))}}function Ht(e,t){for(var n=-1,r=e.length,i=0,a=[];++n",""":'"',"'":"'"});var $t=function e(t){var n,G=(t=null==t?qe:$t.defaults(qe.Object(),t,$t.pick(qe,Ie))).Array,ce=t.Date,fe=t.Error,de=t.Function,pe=t.Math,he=t.Object,ve=t.RegExp,ge=t.String,me=t.TypeError,ye=G.prototype,be=de.prototype,we=he.prototype,_e=t["__core-js_shared__"],xe=be.toString,ke=we.hasOwnProperty,Ce=0,Oe=(n=/[^.]+$/.exec(_e&&_e.keys&&_e.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Ee=we.toString,Se=xe.call(he),Te=qe._,je=ve("^"+xe.call(ke).replace(V,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ae=$e?t.Buffer:void 0,Re=t.Symbol,Be=t.Uint8Array,We=Ae?Ae.allocUnsafe:void 0,Ve=Bt(he.getPrototypeOf,he),Ye=he.create,Ge=we.propertyIsEnumerable,Ke=ye.splice,Ze=Re?Re.isConcatSpreadable:void 0,gt=Re?Re.iterator:void 0,Ct=Re?Re.toStringTag:void 0,Kt=function(){try{var e=ti(he,"defineProperty");return e({},"",{}),e}catch(e){}}(),Zt=t.clearTimeout!==qe.clearTimeout&&t.clearTimeout,Xt=ce&&ce.now!==qe.Date.now&&ce.now,Qt=t.setTimeout!==qe.setTimeout&&t.setTimeout,Jt=pe.ceil,en=pe.floor,tn=he.getOwnPropertySymbols,nn=Ae?Ae.isBuffer:void 0,rn=t.isFinite,on=ye.join,an=Bt(he.keys,he),sn=pe.max,un=pe.min,ln=ce.now,cn=t.parseInt,fn=pe.random,dn=ye.reverse,pn=ti(t,"DataView"),hn=ti(t,"Map"),vn=ti(t,"Promise"),gn=ti(t,"Set"),mn=ti(t,"WeakMap"),yn=ti(he,"create"),bn=mn&&new mn,wn={},_n=Ti(pn),xn=Ti(hn),kn=Ti(vn),Cn=Ti(gn),On=Ti(mn),En=Re?Re.prototype:void 0,Sn=En?En.valueOf:void 0,Tn=En?En.toString:void 0;function jn(e){if(qa(e)&&!Ra(e)&&!(e instanceof Pn)){if(e instanceof An)return e;if(ke.call(e,"__wrapped__"))return ji(e)}return new An(e)}var Mn=function(){function e(){}return function(t){if(!Va(t))return{};if(Ye)return Ye(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();function Ln(){}function An(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=void 0}function Pn(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Rn(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=t?e:t)),e}function Xn(e,t,n,r,o,i){var s,c=1&t,w=2&t,L=4&t;if(n&&(s=o?n(e,r,o,i):n(e)),void 0!==s)return s;if(!Va(e))return e;var A=Ra(e);if(A){if(s=function(e){var t=e.length,n=new e.constructor(t);t&&"string"==typeof e[0]&&ke.call(e,"index")&&(n.index=e.index,n.input=e.input);return n}(e),!c)return bo(e,s)}else{var P=oi(e),R=P==f||P==d;if(za(e))return po(e,c);if(P==v||P==a||R&&!o){if(s=w||R?{}:ai(e),!c)return w?function(e,t){return wo(e,ri(e),t)}(e,function(e,t){return e&&wo(t,xs(t),e)}(s,e)):function(e,t){return wo(e,ni(e),t)}(e,Gn(s,e))}else{if(!Fe[P])return o?e:{};s=function(e,t,n){var r=e.constructor;switch(t){case _:return ho(e);case u:case l:return new r(+e);case x:return function(e,t){var n=t?ho(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}(e,n);case k:case C:case O:case E:case S:case T:case"[object Uint8ClampedArray]":case j:case M:return vo(e,n);case p:return new r;case h:case y:return new r(e);case g:return function(e){var t=new e.constructor(e.source,te.exec(e));return t.lastIndex=e.lastIndex,t}(e);case m:return new r;case b:return o=e,Sn?he(Sn.call(o)):{}}var o}(e,P,c)}}i||(i=new zn);var D=i.get(e);if(D)return D;i.set(e,s),Za(e)?e.forEach((function(r){s.add(Xn(r,t,n,r,e,i))})):Ya(e)&&e.forEach((function(r,o){s.set(o,Xn(r,t,n,o,e,i))}));var I=A?void 0:(L?w?$o:Go:w?xs:_s)(e);return it(I||e,(function(r,o){I&&(r=e[o=r]),Vn(s,o,Xn(r,t,n,o,e,i))})),s}function Qn(e,t,n){var r=n.length;if(null==e)return!r;for(e=he(e);r--;){var o=n[r],i=t[o],a=e[o];if(void 0===a&&!(o in e)||!i(a))return!1}return!0}function Jn(e,t,n){if("function"!=typeof e)throw new me(r);return _i((function(){e.apply(void 0,n)}),t)}function er(e,t,n,r){var o=-1,i=lt,a=!0,s=e.length,u=[],l=t.length;if(!s)return u;n&&(t=ft(t,jt(n))),r?(i=ct,a=!1):t.length>=200&&(i=Lt,a=!1,t=new Nn(t));e:for(;++o-1},Dn.prototype.set=function(e,t){var n=this.__data__,r=qn(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},In.prototype.clear=function(){this.size=0,this.__data__={hash:new Rn,map:new(hn||Dn),string:new Rn}},In.prototype.delete=function(e){var t=Jo(this,e).delete(e);return this.size-=t?1:0,t},In.prototype.get=function(e){return Jo(this,e).get(e)},In.prototype.has=function(e){return Jo(this,e).has(e)},In.prototype.set=function(e,t){var n=Jo(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},Nn.prototype.add=Nn.prototype.push=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(e){return this.__data__.has(e)},zn.prototype.clear=function(){this.__data__=new Dn,this.size=0},zn.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},zn.prototype.get=function(e){return this.__data__.get(e)},zn.prototype.has=function(e){return this.__data__.has(e)},zn.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Dn){var r=n.__data__;if(!hn||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new In(r)}return n.set(e,t),this.size=n.size,this};var tr=ko(lr),nr=ko(cr,!0);function rr(e,t){var n=!0;return tr(e,(function(e,r,o){return n=!!t(e,r,o)})),n}function or(e,t,n){for(var r=-1,o=e.length;++r0&&n(s)?t>1?ar(s,t-1,n,r,o):dt(o,s):r||(o[o.length]=s)}return o}var sr=Co(),ur=Co(!0);function lr(e,t){return e&&sr(e,t,_s)}function cr(e,t){return e&&ur(e,t,_s)}function fr(e,t){return ut(t,(function(t){return Ha(e[t])}))}function dr(e,t){for(var n=0,r=(t=uo(t,e)).length;null!=e&&nt}function gr(e,t){return null!=e&&ke.call(e,t)}function mr(e,t){return null!=e&&t in he(e)}function yr(e,t,n){for(var r=n?ct:lt,o=e[0].length,i=e.length,a=i,s=G(i),u=1/0,l=[];a--;){var c=e[a];a&&t&&(c=ft(c,jt(t))),u=un(c.length,u),s[a]=!n&&(t||o>=120&&c.length>=120)?new Nn(a&&c):void 0}c=e[0];var f=-1,d=s[0];e:for(;++f=s)return u;var l=n[r];return u*("desc"==l?-1:1)}}return e.index-t.index}(e,t,n)}))}function Rr(e,t,n){for(var r=-1,o=t.length,i={};++r-1;)s!==e&&Ke.call(s,u,1),Ke.call(e,u,1);return e}function Ir(e,t){for(var n=e?t.length:0,r=n-1;n--;){var o=t[n];if(n==r||o!==i){var i=o;ui(o)?Ke.call(e,o,1):eo(e,o)}}return e}function Nr(e,t){return e+en(fn()*(t-e+1))}function zr(e,t){var n="";if(!e||t<1||t>9007199254740991)return n;do{t%2&&(n+=e),(t=en(t/2))&&(e+=e)}while(t);return n}function Fr(e,t){return xi(gi(e,t,Gs),e+"")}function Br(e){return Bn(Ms(e))}function Hr(e,t){var n=Ms(e);return Oi(n,Zn(t,0,n.length))}function Ur(e,t,n,r){if(!Va(e))return e;for(var o=-1,i=(t=uo(t,e)).length,a=i-1,s=e;null!=s&&++oo?0:o+t),(n=n>o?o:n)<0&&(n+=o),o=t>n?0:n-t>>>0,t>>>=0;for(var i=G(o);++r>>1,a=e[i];null!==a&&!Qa(a)&&(n?a<=t:a=200){var l=t?null:Fo(e);if(l)return Ut(l);a=!1,o=Lt,u=new Nn}else u=t?[]:s;e:for(;++r=r?e:Yr(e,t,n)}var fo=Zt||function(e){return qe.clearTimeout(e)};function po(e,t){if(t)return e.slice();var n=e.length,r=We?We(n):new e.constructor(n);return e.copy(r),r}function ho(e){var t=new e.constructor(e.byteLength);return new Be(t).set(new Be(e)),t}function vo(e,t){var n=t?ho(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}function go(e,t){if(e!==t){var n=void 0!==e,r=null===e,o=e==e,i=Qa(e),a=void 0!==t,s=null===t,u=t==t,l=Qa(t);if(!s&&!l&&!i&&e>t||i&&a&&u&&!s&&!l||r&&a&&u||!n&&u||!o)return 1;if(!r&&!i&&!l&&e1?n[o-1]:void 0,a=o>2?n[2]:void 0;for(i=e.length>3&&"function"==typeof i?(o--,i):void 0,a&&li(n[0],n[1],a)&&(i=o<3?void 0:i,o=1),t=he(t);++r-1?o[i?t[a]:a]:void 0}}function jo(e){return Yo((function(t){var n=t.length,o=n,i=An.prototype.thru;for(e&&t.reverse();o--;){var a=t[o];if("function"!=typeof a)throw new me(r);if(i&&!s&&"wrapper"==Zo(a))var s=new An([],!0)}for(o=s?o:n;++o1&&y.reverse(),c&&us))return!1;var l=i.get(e),c=i.get(t);if(l&&c)return l==t&&c==e;var f=-1,d=!0,p=2&n?new Nn:void 0;for(i.set(e,t),i.set(t,e);++f-1&&e%1==0&&e1?"& ":"")+t[r],t=t.join(n>2?", ":" "),e.replace($,"{\n/* [wrapped with "+t+"] */\n")}(r,function(e,t){return it(i,(function(n){var r="_."+n[0];t&n[1]&&!lt(e,r)&&e.push(r)})),e.sort()}(function(e){var t=e.match(K);return t?t[1].split(Z):[]}(r),n)))}function Ci(e){var t=0,n=0;return function(){var r=ln(),o=16-(r-n);if(n=r,o>0){if(++t>=800)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function Oi(e,t){var n=-1,r=e.length,o=r-1;for(t=void 0===t?r:t;++n1?e[t-1]:void 0;return n="function"==typeof n?(e.pop(),n):void 0,Ki(e,n)}));function na(e){var t=jn(e);return t.__chain__=!0,t}function ra(e,t){return t(e)}var oa=Yo((function(e){var t=e.length,n=t?e[0]:0,r=this.__wrapped__,o=function(t){return Kn(t,e)};return!(t>1||this.__actions__.length)&&r instanceof Pn&&ui(n)?((r=r.slice(n,+n+(t?1:0))).__actions__.push({func:ra,args:[o],thisArg:void 0}),new An(r,this.__chain__).thru((function(e){return t&&!e.length&&e.push(void 0),e}))):this.thru(o)}));var ia=_o((function(e,t,n){ke.call(e,n)?++e[n]:$n(e,n,1)}));var aa=To(Pi),sa=To(Ri);function ua(e,t){return(Ra(e)?it:tr)(e,Qo(t,3))}function la(e,t){return(Ra(e)?at:nr)(e,Qo(t,3))}var ca=_o((function(e,t,n){ke.call(e,n)?e[n].push(t):$n(e,n,[t])}));var fa=Fr((function(e,t,n){var r=-1,o="function"==typeof t,i=Ia(e)?G(e.length):[];return tr(e,(function(e){i[++r]=o?rt(t,e,n):br(e,t,n)})),i})),da=_o((function(e,t,n){$n(e,n,t)}));function pa(e,t){return(Ra(e)?ft:Tr)(e,Qo(t,3))}var ha=_o((function(e,t,n){e[n?0:1].push(t)}),(function(){return[[],[]]}));var va=Fr((function(e,t){if(null==e)return[];var n=t.length;return n>1&&li(e,t[0],t[1])?t=[]:n>2&&li(t[0],t[1],t[2])&&(t=[t[0]]),Pr(e,ar(t,1),[])})),ga=Xt||function(){return qe.Date.now()};function ma(e,t,n){return t=n?void 0:t,Ho(e,128,void 0,void 0,void 0,void 0,t=e&&null==t?e.length:t)}function ya(e,t){var n;if("function"!=typeof t)throw new me(r);return e=os(e),function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=void 0),n}}var ba=Fr((function(e,t,n){var r=1;if(n.length){var o=Ht(n,Xo(ba));r|=32}return Ho(e,r,t,n,o)})),wa=Fr((function(e,t,n){var r=3;if(n.length){var o=Ht(n,Xo(wa));r|=32}return Ho(t,r,e,n,o)}));function _a(e,t,n){var o,i,a,s,u,l,c=0,f=!1,d=!1,p=!0;if("function"!=typeof e)throw new me(r);function h(t){var n=o,r=i;return o=i=void 0,c=t,s=e.apply(r,n)}function v(e){return c=e,u=_i(m,t),f?h(e):s}function g(e){var n=e-l;return void 0===l||n>=t||n<0||d&&e-c>=a}function m(){var e=ga();if(g(e))return y(e);u=_i(m,function(e){var n=t-(e-l);return d?un(n,a-(e-c)):n}(e))}function y(e){return u=void 0,p&&o?h(e):(o=i=void 0,s)}function b(){var e=ga(),n=g(e);if(o=arguments,i=this,l=e,n){if(void 0===u)return v(l);if(d)return fo(u),u=_i(m,t),h(l)}return void 0===u&&(u=_i(m,t)),s}return t=as(t)||0,Va(n)&&(f=!!n.leading,a=(d="maxWait"in n)?sn(as(n.maxWait)||0,t):a,p="trailing"in n?!!n.trailing:p),b.cancel=function(){void 0!==u&&fo(u),c=0,o=l=i=u=void 0},b.flush=function(){return void 0===u?s:y(ga())},b}var xa=Fr((function(e,t){return Jn(e,1,t)})),ka=Fr((function(e,t,n){return Jn(e,as(t)||0,n)}));function Ca(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new me(r);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=e.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(Ca.Cache||In),n}function Oa(e){if("function"!=typeof e)throw new me(r);return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}Ca.Cache=In;var Ea=lo((function(e,t){var n=(t=1==t.length&&Ra(t[0])?ft(t[0],jt(Qo())):ft(ar(t,1),jt(Qo()))).length;return Fr((function(r){for(var o=-1,i=un(r.length,n);++o=t})),Pa=wr(function(){return arguments}())?wr:function(e){return qa(e)&&ke.call(e,"callee")&&!Ge.call(e,"callee")},Ra=G.isArray,Da=Xe?jt(Xe):function(e){return qa(e)&&hr(e)==_};function Ia(e){return null!=e&&Wa(e.length)&&!Ha(e)}function Na(e){return qa(e)&&Ia(e)}var za=nn||au,Fa=Qe?jt(Qe):function(e){return qa(e)&&hr(e)==l};function Ba(e){if(!qa(e))return!1;var t=hr(e);return t==c||"[object DOMException]"==t||"string"==typeof e.message&&"string"==typeof e.name&&!$a(e)}function Ha(e){if(!Va(e))return!1;var t=hr(e);return t==f||t==d||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Ua(e){return"number"==typeof e&&e==os(e)}function Wa(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}function Va(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function qa(e){return null!=e&&"object"==typeof e}var Ya=Je?jt(Je):function(e){return qa(e)&&oi(e)==p};function Ga(e){return"number"==typeof e||qa(e)&&hr(e)==h}function $a(e){if(!qa(e)||hr(e)!=v)return!1;var t=Ve(e);if(null===t)return!0;var n=ke.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&xe.call(n)==Se}var Ka=et?jt(et):function(e){return qa(e)&&hr(e)==g};var Za=tt?jt(tt):function(e){return qa(e)&&oi(e)==m};function Xa(e){return"string"==typeof e||!Ra(e)&&qa(e)&&hr(e)==y}function Qa(e){return"symbol"==typeof e||qa(e)&&hr(e)==b}var Ja=nt?jt(nt):function(e){return qa(e)&&Wa(e.length)&&!!ze[hr(e)]};var es=Io(Sr),ts=Io((function(e,t){return e<=t}));function ns(e){if(!e)return[];if(Ia(e))return Xa(e)?qt(e):bo(e);if(gt&&e[gt])return function(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}(e[gt]());var t=oi(e);return(t==p?Ft:t==m?Ut:Ms)(e)}function rs(e){return e?(e=as(e))===1/0||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}function os(e){var t=rs(e),n=t%1;return t==t?n?t-n:t:0}function is(e){return e?Zn(os(e),0,4294967295):0}function as(e){if("number"==typeof e)return e;if(Qa(e))return NaN;if(Va(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Va(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=Tt(e);var n=re.test(e);return n||ie.test(e)?Ue(e.slice(2),n?2:8):ne.test(e)?NaN:+e}function ss(e){return wo(e,xs(e))}function us(e){return null==e?"":Qr(e)}var ls=xo((function(e,t){if(pi(t)||Ia(t))wo(t,_s(t),e);else for(var n in t)ke.call(t,n)&&Vn(e,n,t[n])})),cs=xo((function(e,t){wo(t,xs(t),e)})),fs=xo((function(e,t,n,r){wo(t,xs(t),e,r)})),ds=xo((function(e,t,n,r){wo(t,_s(t),e,r)})),ps=Yo(Kn);var hs=Fr((function(e,t){e=he(e);var n=-1,r=t.length,o=r>2?t[2]:void 0;for(o&&li(t[0],t[1],o)&&(r=1);++n1),t})),wo(e,$o(e),n),r&&(n=Xn(n,7,Vo));for(var o=t.length;o--;)eo(n,t[o]);return n}));var Es=Yo((function(e,t){return null==e?{}:function(e,t){return Rr(e,t,(function(t,n){return ms(e,n)}))}(e,t)}));function Ss(e,t){if(null==e)return{};var n=ft($o(e),(function(e){return[e]}));return t=Qo(t),Rr(e,n,(function(e,n){return t(e,n[0])}))}var Ts=Bo(_s),js=Bo(xs);function Ms(e){return null==e?[]:Mt(e,_s(e))}var Ls=Eo((function(e,t,n){return t=t.toLowerCase(),e+(n?As(t):t)}));function As(e){return Bs(us(e).toLowerCase())}function Ps(e){return(e=us(e))&&e.replace(se,Dt).replace(Le,"")}var Rs=Eo((function(e,t,n){return e+(n?"-":"")+t.toLowerCase()})),Ds=Eo((function(e,t,n){return e+(n?" ":"")+t.toLowerCase()})),Is=Oo("toLowerCase");var Ns=Eo((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));var zs=Eo((function(e,t,n){return e+(n?" ":"")+Bs(t)}));var Fs=Eo((function(e,t,n){return e+(n?" ":"")+t.toUpperCase()})),Bs=Oo("toUpperCase");function Hs(e,t,n){return e=us(e),void 0===(t=n?void 0:t)?function(e){return De.test(e)}(e)?function(e){return e.match(Pe)||[]}(e):function(e){return e.match(X)||[]}(e):e.match(t)||[]}var Us=Fr((function(e,t){try{return rt(e,void 0,t)}catch(e){return Ba(e)?e:new fe(e)}})),Ws=Yo((function(e,t){return it(t,(function(t){t=Si(t),$n(e,t,ba(e[t],e))})),e}));function Vs(e){return function(){return e}}var qs=jo(),Ys=jo(!0);function Gs(e){return e}function $s(e){return Cr("function"==typeof e?e:Xn(e,1))}var Ks=Fr((function(e,t){return function(n){return br(n,e,t)}})),Zs=Fr((function(e,t){return function(n){return br(e,n,t)}}));function Xs(e,t,n){var r=_s(t),o=fr(t,r);null!=n||Va(t)&&(o.length||!r.length)||(n=t,t=e,e=this,o=fr(t,_s(t)));var i=!(Va(n)&&"chain"in n&&!n.chain),a=Ha(e);return it(o,(function(n){var r=t[n];e[n]=r,a&&(e.prototype[n]=function(){var t=this.__chain__;if(i||t){var n=e(this.__wrapped__),o=n.__actions__=bo(this.__actions__);return o.push({func:r,args:arguments,thisArg:e}),n.__chain__=t,n}return r.apply(e,dt([this.value()],arguments))})})),e}function Qs(){}var Js=Po(ft),eu=Po(st),tu=Po(vt);function nu(e){return ci(e)?kt(Si(e)):function(e){return function(t){return dr(t,e)}}(e)}var ru=Do(),ou=Do(!0);function iu(){return[]}function au(){return!1}var su=Ao((function(e,t){return e+t}),0),uu=zo("ceil"),lu=Ao((function(e,t){return e/t}),1),cu=zo("floor");var fu,du=Ao((function(e,t){return e*t}),1),pu=zo("round"),hu=Ao((function(e,t){return e-t}),0);return jn.after=function(e,t){if("function"!=typeof t)throw new me(r);return e=os(e),function(){if(--e<1)return t.apply(this,arguments)}},jn.ary=ma,jn.assign=ls,jn.assignIn=cs,jn.assignInWith=fs,jn.assignWith=ds,jn.at=ps,jn.before=ya,jn.bind=ba,jn.bindAll=Ws,jn.bindKey=wa,jn.castArray=function(){if(!arguments.length)return[];var e=arguments[0];return Ra(e)?e:[e]},jn.chain=na,jn.chunk=function(e,t,n){t=(n?li(e,t,n):void 0===t)?1:sn(os(t),0);var r=null==e?0:e.length;if(!r||t<1)return[];for(var o=0,i=0,a=G(Jt(r/t));oo?0:o+n),(r=void 0===r||r>o?o:os(r))<0&&(r+=o),r=n>r?0:is(r);n>>0)?(e=us(e))&&("string"==typeof t||null!=t&&!Ka(t))&&!(t=Qr(t))&&zt(e)?co(qt(e),0,n):e.split(t,n):[]},jn.spread=function(e,t){if("function"!=typeof e)throw new me(r);return t=null==t?0:sn(os(t),0),Fr((function(n){var r=n[t],o=co(n,0,t);return r&&dt(o,r),rt(e,this,o)}))},jn.tail=function(e){var t=null==e?0:e.length;return t?Yr(e,1,t):[]},jn.take=function(e,t,n){return e&&e.length?Yr(e,0,(t=n||void 0===t?1:os(t))<0?0:t):[]},jn.takeRight=function(e,t,n){var r=null==e?0:e.length;return r?Yr(e,(t=r-(t=n||void 0===t?1:os(t)))<0?0:t,r):[]},jn.takeRightWhile=function(e,t){return e&&e.length?no(e,Qo(t,3),!1,!0):[]},jn.takeWhile=function(e,t){return e&&e.length?no(e,Qo(t,3)):[]},jn.tap=function(e,t){return t(e),e},jn.throttle=function(e,t,n){var o=!0,i=!0;if("function"!=typeof e)throw new me(r);return Va(n)&&(o="leading"in n?!!n.leading:o,i="trailing"in n?!!n.trailing:i),_a(e,t,{leading:o,maxWait:t,trailing:i})},jn.thru=ra,jn.toArray=ns,jn.toPairs=Ts,jn.toPairsIn=js,jn.toPath=function(e){return Ra(e)?ft(e,Si):Qa(e)?[e]:bo(Ei(us(e)))},jn.toPlainObject=ss,jn.transform=function(e,t,n){var r=Ra(e),o=r||za(e)||Ja(e);if(t=Qo(t,4),null==n){var i=e&&e.constructor;n=o?r?new i:[]:Va(e)&&Ha(i)?Mn(Ve(e)):{}}return(o?it:lr)(e,(function(e,r,o){return t(n,e,r,o)})),n},jn.unary=function(e){return ma(e,1)},jn.union=qi,jn.unionBy=Yi,jn.unionWith=Gi,jn.uniq=function(e){return e&&e.length?Jr(e):[]},jn.uniqBy=function(e,t){return e&&e.length?Jr(e,Qo(t,2)):[]},jn.uniqWith=function(e,t){return t="function"==typeof t?t:void 0,e&&e.length?Jr(e,void 0,t):[]},jn.unset=function(e,t){return null==e||eo(e,t)},jn.unzip=$i,jn.unzipWith=Ki,jn.update=function(e,t,n){return null==e?e:to(e,t,so(n))},jn.updateWith=function(e,t,n,r){return r="function"==typeof r?r:void 0,null==e?e:to(e,t,so(n),r)},jn.values=Ms,jn.valuesIn=function(e){return null==e?[]:Mt(e,xs(e))},jn.without=Zi,jn.words=Hs,jn.wrap=function(e,t){return Sa(so(t),e)},jn.xor=Xi,jn.xorBy=Qi,jn.xorWith=Ji,jn.zip=ea,jn.zipObject=function(e,t){return io(e||[],t||[],Vn)},jn.zipObjectDeep=function(e,t){return io(e||[],t||[],Ur)},jn.zipWith=ta,jn.entries=Ts,jn.entriesIn=js,jn.extend=cs,jn.extendWith=fs,Xs(jn,jn),jn.add=su,jn.attempt=Us,jn.camelCase=Ls,jn.capitalize=As,jn.ceil=uu,jn.clamp=function(e,t,n){return void 0===n&&(n=t,t=void 0),void 0!==n&&(n=(n=as(n))==n?n:0),void 0!==t&&(t=(t=as(t))==t?t:0),Zn(as(e),t,n)},jn.clone=function(e){return Xn(e,4)},jn.cloneDeep=function(e){return Xn(e,5)},jn.cloneDeepWith=function(e,t){return Xn(e,5,t="function"==typeof t?t:void 0)},jn.cloneWith=function(e,t){return Xn(e,4,t="function"==typeof t?t:void 0)},jn.conformsTo=function(e,t){return null==t||Qn(e,t,_s(t))},jn.deburr=Ps,jn.defaultTo=function(e,t){return null==e||e!=e?t:e},jn.divide=lu,jn.endsWith=function(e,t,n){e=us(e),t=Qr(t);var r=e.length,o=n=void 0===n?r:Zn(os(n),0,r);return(n-=t.length)>=0&&e.slice(n,o)==t},jn.eq=Ma,jn.escape=function(e){return(e=us(e))&&N.test(e)?e.replace(D,It):e},jn.escapeRegExp=function(e){return(e=us(e))&&q.test(e)?e.replace(V,"\\$&"):e},jn.every=function(e,t,n){var r=Ra(e)?st:rr;return n&&li(e,t,n)&&(t=void 0),r(e,Qo(t,3))},jn.find=aa,jn.findIndex=Pi,jn.findKey=function(e,t){return mt(e,Qo(t,3),lr)},jn.findLast=sa,jn.findLastIndex=Ri,jn.findLastKey=function(e,t){return mt(e,Qo(t,3),cr)},jn.floor=cu,jn.forEach=ua,jn.forEachRight=la,jn.forIn=function(e,t){return null==e?e:sr(e,Qo(t,3),xs)},jn.forInRight=function(e,t){return null==e?e:ur(e,Qo(t,3),xs)},jn.forOwn=function(e,t){return e&&lr(e,Qo(t,3))},jn.forOwnRight=function(e,t){return e&&cr(e,Qo(t,3))},jn.get=gs,jn.gt=La,jn.gte=Aa,jn.has=function(e,t){return null!=e&&ii(e,t,gr)},jn.hasIn=ms,jn.head=Ii,jn.identity=Gs,jn.includes=function(e,t,n,r){e=Ia(e)?e:Ms(e),n=n&&!r?os(n):0;var o=e.length;return n<0&&(n=sn(o+n,0)),Xa(e)?n<=o&&e.indexOf(t,n)>-1:!!o&&bt(e,t,n)>-1},jn.indexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=null==n?0:os(n);return o<0&&(o=sn(r+o,0)),bt(e,t,o)},jn.inRange=function(e,t,n){return t=rs(t),void 0===n?(n=t,t=0):n=rs(n),function(e,t,n){return e>=un(t,n)&&e=-9007199254740991&&e<=9007199254740991},jn.isSet=Za,jn.isString=Xa,jn.isSymbol=Qa,jn.isTypedArray=Ja,jn.isUndefined=function(e){return void 0===e},jn.isWeakMap=function(e){return qa(e)&&oi(e)==w},jn.isWeakSet=function(e){return qa(e)&&"[object WeakSet]"==hr(e)},jn.join=function(e,t){return null==e?"":on.call(e,t)},jn.kebabCase=Rs,jn.last=Bi,jn.lastIndexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=r;return void 0!==n&&(o=(o=os(n))<0?sn(r+o,0):un(o,r-1)),t==t?function(e,t,n){for(var r=n+1;r--;)if(e[r]===t)return r;return r}(e,t,o):yt(e,_t,o,!0)},jn.lowerCase=Ds,jn.lowerFirst=Is,jn.lt=es,jn.lte=ts,jn.max=function(e){return e&&e.length?or(e,Gs,vr):void 0},jn.maxBy=function(e,t){return e&&e.length?or(e,Qo(t,2),vr):void 0},jn.mean=function(e){return xt(e,Gs)},jn.meanBy=function(e,t){return xt(e,Qo(t,2))},jn.min=function(e){return e&&e.length?or(e,Gs,Sr):void 0},jn.minBy=function(e,t){return e&&e.length?or(e,Qo(t,2),Sr):void 0},jn.stubArray=iu,jn.stubFalse=au,jn.stubObject=function(){return{}},jn.stubString=function(){return""},jn.stubTrue=function(){return!0},jn.multiply=du,jn.nth=function(e,t){return e&&e.length?Ar(e,os(t)):void 0},jn.noConflict=function(){return qe._===this&&(qe._=Te),this},jn.noop=Qs,jn.now=ga,jn.pad=function(e,t,n){e=us(e);var r=(t=os(t))?Vt(e):0;if(!t||r>=t)return e;var o=(t-r)/2;return Ro(en(o),n)+e+Ro(Jt(o),n)},jn.padEnd=function(e,t,n){e=us(e);var r=(t=os(t))?Vt(e):0;return t&&rt){var r=e;e=t,t=r}if(n||e%1||t%1){var o=fn();return un(e+o*(t-e+He("1e-"+((o+"").length-1))),t)}return Nr(e,t)},jn.reduce=function(e,t,n){var r=Ra(e)?pt:Ot,o=arguments.length<3;return r(e,Qo(t,4),n,o,tr)},jn.reduceRight=function(e,t,n){var r=Ra(e)?ht:Ot,o=arguments.length<3;return r(e,Qo(t,4),n,o,nr)},jn.repeat=function(e,t,n){return t=(n?li(e,t,n):void 0===t)?1:os(t),zr(us(e),t)},jn.replace=function(){var e=arguments,t=us(e[0]);return e.length<3?t:t.replace(e[1],e[2])},jn.result=function(e,t,n){var r=-1,o=(t=uo(t,e)).length;for(o||(o=1,e=void 0);++r9007199254740991)return[];var n=4294967295,r=un(e,4294967295);e-=4294967295;for(var o=St(r,t=Qo(t));++n=i)return e;var s=n-Vt(r);if(s<1)return r;var u=a?co(a,0,s).join(""):e.slice(0,s);if(void 0===o)return u+r;if(a&&(s+=u.length-s),Ka(o)){if(e.slice(s).search(o)){var l,c=u;for(o.global||(o=ve(o.source,us(te.exec(o))+"g")),o.lastIndex=0;l=o.exec(c);)var f=l.index;u=u.slice(0,void 0===f?s:f)}}else if(e.indexOf(Qr(o),s)!=s){var d=u.lastIndexOf(o);d>-1&&(u=u.slice(0,d))}return u+r},jn.unescape=function(e){return(e=us(e))&&I.test(e)?e.replace(R,Gt):e},jn.uniqueId=function(e){var t=++Ce;return us(e)+t},jn.upperCase=Fs,jn.upperFirst=Bs,jn.each=ua,jn.eachRight=la,jn.first=Ii,Xs(jn,(fu={},lr(jn,(function(e,t){ke.call(jn.prototype,t)||(fu[t]=e)})),fu),{chain:!1}),jn.VERSION="4.17.21",it(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(e){jn[e].placeholder=jn})),it(["drop","take"],(function(e,t){Pn.prototype[e]=function(n){n=void 0===n?1:sn(os(n),0);var r=this.__filtered__&&!t?new Pn(this):this.clone();return r.__filtered__?r.__takeCount__=un(n,r.__takeCount__):r.__views__.push({size:un(n,4294967295),type:e+(r.__dir__<0?"Right":"")}),r},Pn.prototype[e+"Right"]=function(t){return this.reverse()[e](t).reverse()}})),it(["filter","map","takeWhile"],(function(e,t){var n=t+1,r=1==n||3==n;Pn.prototype[e]=function(e){var t=this.clone();return t.__iteratees__.push({iteratee:Qo(e,3),type:n}),t.__filtered__=t.__filtered__||r,t}})),it(["head","last"],(function(e,t){var n="take"+(t?"Right":"");Pn.prototype[e]=function(){return this[n](1).value()[0]}})),it(["initial","tail"],(function(e,t){var n="drop"+(t?"":"Right");Pn.prototype[e]=function(){return this.__filtered__?new Pn(this):this[n](1)}})),Pn.prototype.compact=function(){return this.filter(Gs)},Pn.prototype.find=function(e){return this.filter(e).head()},Pn.prototype.findLast=function(e){return this.reverse().find(e)},Pn.prototype.invokeMap=Fr((function(e,t){return"function"==typeof e?new Pn(this):this.map((function(n){return br(n,e,t)}))})),Pn.prototype.reject=function(e){return this.filter(Oa(Qo(e)))},Pn.prototype.slice=function(e,t){e=os(e);var n=this;return n.__filtered__&&(e>0||t<0)?new Pn(n):(e<0?n=n.takeRight(-e):e&&(n=n.drop(e)),void 0!==t&&(n=(t=os(t))<0?n.dropRight(-t):n.take(t-e)),n)},Pn.prototype.takeRightWhile=function(e){return this.reverse().takeWhile(e).reverse()},Pn.prototype.toArray=function(){return this.take(4294967295)},lr(Pn.prototype,(function(e,t){var n=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),o=jn[r?"take"+("last"==t?"Right":""):t],i=r||/^find/.test(t);o&&(jn.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,s=t instanceof Pn,u=a[0],l=s||Ra(t),c=function(e){var t=o.apply(jn,dt([e],a));return r&&f?t[0]:t};l&&n&&"function"==typeof u&&1!=u.length&&(s=l=!1);var f=this.__chain__,d=!!this.__actions__.length,p=i&&!f,h=s&&!d;if(!i&&l){t=h?t:new Pn(this);var v=e.apply(t,a);return v.__actions__.push({func:ra,args:[c],thisArg:void 0}),new An(v,f)}return p&&h?e.apply(this,a):(v=this.thru(c),p?r?v.value()[0]:v.value():v)})})),it(["pop","push","shift","sort","splice","unshift"],(function(e){var t=ye[e],n=/^(?:push|sort|unshift)$/.test(e)?"tap":"thru",r=/^(?:pop|shift)$/.test(e);jn.prototype[e]=function(){var e=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(Ra(o)?o:[],e)}return this[n]((function(n){return t.apply(Ra(n)?n:[],e)}))}})),lr(Pn.prototype,(function(e,t){var n=jn[t];if(n){var r=n.name+"";ke.call(wn,r)||(wn[r]=[]),wn[r].push({name:t,func:n})}})),wn[Mo(void 0,2).name]=[{name:"wrapper",func:void 0}],Pn.prototype.clone=function(){var e=new Pn(this.__wrapped__);return e.__actions__=bo(this.__actions__),e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=bo(this.__iteratees__),e.__takeCount__=this.__takeCount__,e.__views__=bo(this.__views__),e},Pn.prototype.reverse=function(){if(this.__filtered__){var e=new Pn(this);e.__dir__=-1,e.__filtered__=!0}else(e=this.clone()).__dir__*=-1;return e},Pn.prototype.value=function(){var e=this.__wrapped__.value(),t=this.__dir__,n=Ra(e),r=t<0,o=n?e.length:0,i=function(e,t,n){var r=-1,o=n.length;for(;++r=this.__values__.length;return{done:e,value:e?void 0:this.__values__[this.__index__++]}},jn.prototype.plant=function(e){for(var t,n=this;n instanceof Ln;){var r=ji(n);r.__index__=0,r.__values__=void 0,t?o.__wrapped__=r:t=r;var o=r;n=n.__wrapped__}return o.__wrapped__=e,t},jn.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof Pn){var t=e;return this.__actions__.length&&(t=new Pn(this)),(t=t.reverse()).__actions__.push({func:ra,args:[Vi],thisArg:void 0}),new An(t,this.__chain__)}return this.thru(Vi)},jn.prototype.toJSON=jn.prototype.valueOf=jn.prototype.value=function(){return ro(this.__wrapped__,this.__actions__)},jn.prototype.first=jn.prototype.head,gt&&(jn.prototype[gt]=function(){return this}),jn}();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(qe._=$t,define((function(){return $t}))):Ge?((Ge.exports=$t)._=$t,Ye._=$t):qe._=$t}).call(this)}).call(this,n(31),n(57)(e))},function(e,t,n){"use strict";n.d(t,"l",(function(){return s})),n.d(t,"c",(function(){return u})),n.d(t,"v",(function(){return l})),n.d(t,"s",(function(){return c})),n.d(t,"w",(function(){return f})),n.d(t,"h",(function(){return d})),n.d(t,"y",(function(){return p})),n.d(t,"u",(function(){return h})),n.d(t,"f",(function(){return v})),n.d(t,"k",(function(){return g})),n.d(t,"n",(function(){return m})),n.d(t,"g",(function(){return b})),n.d(t,"r",(function(){return w})),n.d(t,"i",(function(){return _})),n.d(t,"e",(function(){return x})),n.d(t,"x",(function(){return k})),n.d(t,"d",(function(){return C})),n.d(t,"b",(function(){return O})),n.d(t,"q",(function(){return E})),n.d(t,"m",(function(){return S})),n.d(t,"j",(function(){return T})),n.d(t,"a",(function(){return M})),n.d(t,"o",(function(){return L})),n.d(t,"t",(function(){return A})),n.d(t,"p",(function(){return P}));var r=n(43),o=n(20),i=n(12),a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function s(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=Object.keys(e),r=Object.keys(t),o=[],i=0;i1&&void 0!==arguments[1]?arguments[1]:[],n=t.reduce((function(t,n){return!!(t||e instanceof n)||t}),!1);return!(void 0===e||!(n||l(e)&&"[object Object]"===Object.prototype.toString.call(e)&&(e.constructor===Object||null===Object.getPrototypeOf(e))||"number"==typeof e||"string"==typeof e||"boolean"==typeof e||null===e||Array.isArray(e)))}function d(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[];return Array.isArray(e)?e:"string"==typeof e?e.split("."):[]}function p(e){throw new Error("Cerebral - "+e)}function h(){return!1}function v(e,t,n){var r=void 0;return function(){var o=this,i=arguments,a=function(){r=null,n||e.apply(o,i)},s=n&&!r;clearTimeout(r),r=setTimeout(a,t),s&&e.apply(o,i)}}function g(e){if(e&&!f(e)){var t=e.constructor.name;try{Object.defineProperty(e,"toJSON",{value:function(){return"["+t+"]"}})}catch(e){}}return e}function m(e){return Object.assign(Object.keys(e.providers||{}).reduce((function(t,n){return t[n]=e.providers[n]instanceof i.b?e.providers[n]:new i.b(e.providers[n]),t}),{}),Object.keys(e.modules||{}).reduce((function(t,n){return Object.assign(t,m(e.modules[n]))}),{}))}function y(e){return Object.keys(e).reduce((function(t,n){return e[n].children?t.concat(e[n]).concat(y(e[n].children)):t.concat(e[n])}),[])}function b(e,t){for(var n=[],r=0;r0&&void 0===e&&p('You are extracting with path "'+t+'", but it is not valid for this object'),e[n]}),e)}}function _(e,t){return c(t)&&-1===e.indexOf("*")?e+".**":e}function x(e){return{isTag:function(e){if(!(e instanceof r.Tag))return!1;for(var t=arguments.length,n=Array(t>1?t-1:0),o=1;o0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=function(t){return d(t).reduce((function(e,t){return e?e[t]:void 0}),e)};return{options:{},on:function(){},getState:n,model:{get:n},getSequence:function(e){return t[e]||function(){}},dependencyStore:{addEntity:k,removeEntity:k}}}function O(e){if(c(e)&&!(e instanceof o.a)){for(var t in e)O(e[t]);!e.__CerebralState&&Object.defineProperty(e,"__CerebralState",{value:!0})}return e}function E(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return Object.keys(e).reduce((function(t,n){return!t&&c(e[n])&&"__CerebralState"in e[n]?n:t}),null)}function S(e,t){var n=Array.isArray(e)?e:d(e);return n.reduce((function(t,r){return t.modules[r]||p('The path "'+n.join(".")+'" is invalid, can not find module. Does the path "'+n.splice(0,e.length-1).join(".")+'" exist?'),t.modules[r]}),t)}function T(e,t,n){var r=Object.keys(e.modules||{}).reduce((function(r,o){return r[o]=T(e.modules[o],t,n),r}),{});if(e[t]){var o=Object.keys(e[t]).reduce((function(n,r){var o=Object.getOwnPropertyDescriptor(e[t],r);return o&&"get"in o?Object.defineProperty(n,r,o):n[r]=e[t][r],n}),r);return n?n(o,e):o}return r}var j=[];function M(e,t){-1===j.indexOf(e)&&(j.push(e),console.warn(e+" is DEPRECATED - "+t))}function L(e,t){var n=t.execution.name.split(".");return n.splice(0,n.length-1).concat(e).join(".")}function A(e){return e instanceof o.a||e instanceof o.b}function P(e,t,n){var r=[];return function e(t,n,o){var i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:[];if(A(n)||A(o))return o;if(l(n)&&l(o)){var a=Object.keys(n).concat(Object.keys(o)).reduce((function(e,t){return-1===e.indexOf(t)?e.concat(t):e}),[]),s=!0,u=!1,c=void 0;try{for(var f,d=a[Symbol.iterator]();!(s=(f=d.next()).done);s=!0){var p=f.value;e(t[p],n[p],o[p],i.concat(p))}}catch(e){u=!0,c=e}finally{try{!s&&d.return&&d.return()}finally{if(u)throw c}}}else"function"!=typeof o&&(Array.isArray(n)&&Array.isArray(o)||o===t&&n!==t?r.push({path:i.slice(),value:n}):o!==t&&r.push({path:i.slice(),value:o}))}(e,t,n),r}},function(e,t,n){(function(e,n){(function(){var r="Expected a function",o="__lodash_placeholder__",i=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],a="[object Arguments]",s="[object Array]",u="[object Boolean]",l="[object Date]",c="[object Error]",f="[object Function]",d="[object GeneratorFunction]",p="[object Map]",h="[object Number]",v="[object Object]",g="[object RegExp]",m="[object Set]",y="[object String]",b="[object Symbol]",w="[object WeakMap]",_="[object ArrayBuffer]",x="[object DataView]",k="[object Float32Array]",C="[object Float64Array]",O="[object Int8Array]",E="[object Int16Array]",S="[object Int32Array]",T="[object Uint8Array]",j="[object Uint16Array]",M="[object Uint32Array]",L=/\b__p \+= '';/g,A=/\b(__p \+=) '' \+/g,P=/(__e\(.*?\)|\b__t\)) \+\n'';/g,R=/&(?:amp|lt|gt|quot|#39);/g,D=/[&<>"']/g,I=RegExp(R.source),N=RegExp(D.source),z=/<%-([\s\S]+?)%>/g,F=/<%([\s\S]+?)%>/g,B=/<%=([\s\S]+?)%>/g,H=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,U=/^\w*$/,W=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,V=/[\\^$.*+?()[\]{}|]/g,q=RegExp(V.source),Y=/^\s+/,G=/\s/,$=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,K=/\{\n\/\* \[wrapped with (.+)\] \*/,Z=/,? & /,X=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Q=/[()=,{}\[\]\/\s]/,J=/\\(\\)?/g,ee=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,te=/\w*$/,ne=/^[-+]0x[0-9a-f]+$/i,re=/^0b[01]+$/i,oe=/^\[object .+?Constructor\]$/,ie=/^0o[0-7]+$/i,ae=/^(?:0|[1-9]\d*)$/,se=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,ue=/($^)/,le=/['\n\r\u2028\u2029\\]/g,ce="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",fe="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",de="[\\ud800-\\udfff]",pe="["+fe+"]",he="["+ce+"]",ve="\\d+",ge="[\\u2700-\\u27bf]",me="[a-z\\xdf-\\xf6\\xf8-\\xff]",ye="[^\\ud800-\\udfff"+fe+ve+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",be="\\ud83c[\\udffb-\\udfff]",we="[^\\ud800-\\udfff]",_e="(?:\\ud83c[\\udde6-\\uddff]){2}",xe="[\\ud800-\\udbff][\\udc00-\\udfff]",ke="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Ce="(?:"+me+"|"+ye+")",Oe="(?:"+ke+"|"+ye+")",Ee="(?:"+he+"|"+be+")"+"?",Se="[\\ufe0e\\ufe0f]?"+Ee+("(?:\\u200d(?:"+[we,_e,xe].join("|")+")[\\ufe0e\\ufe0f]?"+Ee+")*"),Te="(?:"+[ge,_e,xe].join("|")+")"+Se,je="(?:"+[we+he+"?",he,_e,xe,de].join("|")+")",Me=RegExp("['\u2019]","g"),Le=RegExp(he,"g"),Ae=RegExp(be+"(?="+be+")|"+je+Se,"g"),Pe=RegExp([ke+"?"+me+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?="+[pe,ke,"$"].join("|")+")",Oe+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?="+[pe,ke+Ce,"$"].join("|")+")",ke+"?"+Ce+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?",ke+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ve,Te].join("|"),"g"),Re=RegExp("[\\u200d\\ud800-\\udfff"+ce+"\\ufe0e\\ufe0f]"),De=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Ie=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Ne=-1,ze={};ze[k]=ze[C]=ze[O]=ze[E]=ze[S]=ze[T]=ze["[object Uint8ClampedArray]"]=ze[j]=ze[M]=!0,ze[a]=ze[s]=ze[_]=ze[u]=ze[x]=ze[l]=ze[c]=ze[f]=ze[p]=ze[h]=ze[v]=ze[g]=ze[m]=ze[y]=ze[w]=!1;var Fe={};Fe[a]=Fe[s]=Fe[_]=Fe[x]=Fe[u]=Fe[l]=Fe[k]=Fe[C]=Fe[O]=Fe[E]=Fe[S]=Fe[p]=Fe[h]=Fe[v]=Fe[g]=Fe[m]=Fe[y]=Fe[b]=Fe[T]=Fe["[object Uint8ClampedArray]"]=Fe[j]=Fe[M]=!0,Fe[c]=Fe[f]=Fe[w]=!1;var Be={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},He=parseFloat,Ue=parseInt,We="object"==typeof e&&e&&e.Object===Object&&e,Ve="object"==typeof self&&self&&self.Object===Object&&self,qe=We||Ve||Function("return this")(),Ye=t&&!t.nodeType&&t,Ge=Ye&&"object"==typeof n&&n&&!n.nodeType&&n,$e=Ge&&Ge.exports===Ye,Ke=$e&&We.process,Ze=function(){try{var e=Ge&&Ge.require&&Ge.require("util").types;return e||Ke&&Ke.binding&&Ke.binding("util")}catch(e){}}(),Xe=Ze&&Ze.isArrayBuffer,Qe=Ze&&Ze.isDate,Je=Ze&&Ze.isMap,et=Ze&&Ze.isRegExp,tt=Ze&&Ze.isSet,nt=Ze&&Ze.isTypedArray;function rt(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function ot(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o-1}function ct(e,t,n){for(var r=-1,o=null==e?0:e.length;++r-1;);return n}function Pt(e,t){for(var n=e.length;n--&&bt(t,e[n],0)>-1;);return n}function Rt(e,t){for(var n=e.length,r=0;n--;)e[n]===t&&++r;return r}var Dt=Ct({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),It=Ct({"&":"&","<":"<",">":">",'"':""","'":"'"});function Nt(e){return"\\"+Be[e]}function zt(e){return Re.test(e)}function Ft(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}function Bt(e,t){return function(n){return e(t(n))}}function Ht(e,t){for(var n=-1,r=e.length,i=0,a=[];++n",""":'"',"'":"'"});var $t=function e(t){var n,G=(t=null==t?qe:$t.defaults(qe.Object(),t,$t.pick(qe,Ie))).Array,ce=t.Date,fe=t.Error,de=t.Function,pe=t.Math,he=t.Object,ve=t.RegExp,ge=t.String,me=t.TypeError,ye=G.prototype,be=de.prototype,we=he.prototype,_e=t["__core-js_shared__"],xe=be.toString,ke=we.hasOwnProperty,Ce=0,Oe=(n=/[^.]+$/.exec(_e&&_e.keys&&_e.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Ee=we.toString,Se=xe.call(he),Te=qe._,je=ve("^"+xe.call(ke).replace(V,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ae=$e?t.Buffer:void 0,Re=t.Symbol,Be=t.Uint8Array,We=Ae?Ae.allocUnsafe:void 0,Ve=Bt(he.getPrototypeOf,he),Ye=he.create,Ge=we.propertyIsEnumerable,Ke=ye.splice,Ze=Re?Re.isConcatSpreadable:void 0,gt=Re?Re.iterator:void 0,Ct=Re?Re.toStringTag:void 0,Kt=function(){try{var e=ti(he,"defineProperty");return e({},"",{}),e}catch(e){}}(),Zt=t.clearTimeout!==qe.clearTimeout&&t.clearTimeout,Xt=ce&&ce.now!==qe.Date.now&&ce.now,Qt=t.setTimeout!==qe.setTimeout&&t.setTimeout,Jt=pe.ceil,en=pe.floor,tn=he.getOwnPropertySymbols,nn=Ae?Ae.isBuffer:void 0,rn=t.isFinite,on=ye.join,an=Bt(he.keys,he),sn=pe.max,un=pe.min,ln=ce.now,cn=t.parseInt,fn=pe.random,dn=ye.reverse,pn=ti(t,"DataView"),hn=ti(t,"Map"),vn=ti(t,"Promise"),gn=ti(t,"Set"),mn=ti(t,"WeakMap"),yn=ti(he,"create"),bn=mn&&new mn,wn={},_n=Ti(pn),xn=Ti(hn),kn=Ti(vn),Cn=Ti(gn),On=Ti(mn),En=Re?Re.prototype:void 0,Sn=En?En.valueOf:void 0,Tn=En?En.toString:void 0;function jn(e){if(qa(e)&&!Ra(e)&&!(e instanceof Pn)){if(e instanceof An)return e;if(ke.call(e,"__wrapped__"))return ji(e)}return new An(e)}var Mn=function(){function e(){}return function(t){if(!Va(t))return{};if(Ye)return Ye(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();function Ln(){}function An(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=void 0}function Pn(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Rn(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=t?e:t)),e}function Xn(e,t,n,r,o,i){var s,c=1&t,w=2&t,L=4&t;if(n&&(s=o?n(e,r,o,i):n(e)),void 0!==s)return s;if(!Va(e))return e;var A=Ra(e);if(A){if(s=function(e){var t=e.length,n=new e.constructor(t);t&&"string"==typeof e[0]&&ke.call(e,"index")&&(n.index=e.index,n.input=e.input);return n}(e),!c)return bo(e,s)}else{var P=oi(e),R=P==f||P==d;if(za(e))return po(e,c);if(P==v||P==a||R&&!o){if(s=w||R?{}:ai(e),!c)return w?function(e,t){return wo(e,ri(e),t)}(e,function(e,t){return e&&wo(t,xs(t),e)}(s,e)):function(e,t){return wo(e,ni(e),t)}(e,Gn(s,e))}else{if(!Fe[P])return o?e:{};s=function(e,t,n){var r=e.constructor;switch(t){case _:return ho(e);case u:case l:return new r(+e);case x:return function(e,t){var n=t?ho(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}(e,n);case k:case C:case O:case E:case S:case T:case"[object Uint8ClampedArray]":case j:case M:return vo(e,n);case p:return new r;case h:case y:return new r(e);case g:return function(e){var t=new e.constructor(e.source,te.exec(e));return t.lastIndex=e.lastIndex,t}(e);case m:return new r;case b:return o=e,Sn?he(Sn.call(o)):{}}var o}(e,P,c)}}i||(i=new zn);var D=i.get(e);if(D)return D;i.set(e,s),Za(e)?e.forEach((function(r){s.add(Xn(r,t,n,r,e,i))})):Ya(e)&&e.forEach((function(r,o){s.set(o,Xn(r,t,n,o,e,i))}));var I=A?void 0:(L?w?$o:Go:w?xs:_s)(e);return it(I||e,(function(r,o){I&&(r=e[o=r]),Vn(s,o,Xn(r,t,n,o,e,i))})),s}function Qn(e,t,n){var r=n.length;if(null==e)return!r;for(e=he(e);r--;){var o=n[r],i=t[o],a=e[o];if(void 0===a&&!(o in e)||!i(a))return!1}return!0}function Jn(e,t,n){if("function"!=typeof e)throw new me(r);return _i((function(){e.apply(void 0,n)}),t)}function er(e,t,n,r){var o=-1,i=lt,a=!0,s=e.length,u=[],l=t.length;if(!s)return u;n&&(t=ft(t,jt(n))),r?(i=ct,a=!1):t.length>=200&&(i=Lt,a=!1,t=new Nn(t));e:for(;++o-1},Dn.prototype.set=function(e,t){var n=this.__data__,r=qn(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},In.prototype.clear=function(){this.size=0,this.__data__={hash:new Rn,map:new(hn||Dn),string:new Rn}},In.prototype.delete=function(e){var t=Jo(this,e).delete(e);return this.size-=t?1:0,t},In.prototype.get=function(e){return Jo(this,e).get(e)},In.prototype.has=function(e){return Jo(this,e).has(e)},In.prototype.set=function(e,t){var n=Jo(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},Nn.prototype.add=Nn.prototype.push=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(e){return this.__data__.has(e)},zn.prototype.clear=function(){this.__data__=new Dn,this.size=0},zn.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},zn.prototype.get=function(e){return this.__data__.get(e)},zn.prototype.has=function(e){return this.__data__.has(e)},zn.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Dn){var r=n.__data__;if(!hn||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new In(r)}return n.set(e,t),this.size=n.size,this};var tr=ko(lr),nr=ko(cr,!0);function rr(e,t){var n=!0;return tr(e,(function(e,r,o){return n=!!t(e,r,o)})),n}function or(e,t,n){for(var r=-1,o=e.length;++r0&&n(s)?t>1?ar(s,t-1,n,r,o):dt(o,s):r||(o[o.length]=s)}return o}var sr=Co(),ur=Co(!0);function lr(e,t){return e&&sr(e,t,_s)}function cr(e,t){return e&&ur(e,t,_s)}function fr(e,t){return ut(t,(function(t){return Ha(e[t])}))}function dr(e,t){for(var n=0,r=(t=uo(t,e)).length;null!=e&&nt}function gr(e,t){return null!=e&&ke.call(e,t)}function mr(e,t){return null!=e&&t in he(e)}function yr(e,t,n){for(var r=n?ct:lt,o=e[0].length,i=e.length,a=i,s=G(i),u=1/0,l=[];a--;){var c=e[a];a&&t&&(c=ft(c,jt(t))),u=un(c.length,u),s[a]=!n&&(t||o>=120&&c.length>=120)?new Nn(a&&c):void 0}c=e[0];var f=-1,d=s[0];e:for(;++f=s)return u;var l=n[r];return u*("desc"==l?-1:1)}}return e.index-t.index}(e,t,n)}))}function Rr(e,t,n){for(var r=-1,o=t.length,i={};++r-1;)s!==e&&Ke.call(s,u,1),Ke.call(e,u,1);return e}function Ir(e,t){for(var n=e?t.length:0,r=n-1;n--;){var o=t[n];if(n==r||o!==i){var i=o;ui(o)?Ke.call(e,o,1):eo(e,o)}}return e}function Nr(e,t){return e+en(fn()*(t-e+1))}function zr(e,t){var n="";if(!e||t<1||t>9007199254740991)return n;do{t%2&&(n+=e),(t=en(t/2))&&(e+=e)}while(t);return n}function Fr(e,t){return xi(gi(e,t,Gs),e+"")}function Br(e){return Bn(Ms(e))}function Hr(e,t){var n=Ms(e);return Oi(n,Zn(t,0,n.length))}function Ur(e,t,n,r){if(!Va(e))return e;for(var o=-1,i=(t=uo(t,e)).length,a=i-1,s=e;null!=s&&++oo?0:o+t),(n=n>o?o:n)<0&&(n+=o),o=t>n?0:n-t>>>0,t>>>=0;for(var i=G(o);++r>>1,a=e[i];null!==a&&!Qa(a)&&(n?a<=t:a=200){var l=t?null:Fo(e);if(l)return Ut(l);a=!1,o=Lt,u=new Nn}else u=t?[]:s;e:for(;++r=r?e:Yr(e,t,n)}var fo=Zt||function(e){return qe.clearTimeout(e)};function po(e,t){if(t)return e.slice();var n=e.length,r=We?We(n):new e.constructor(n);return e.copy(r),r}function ho(e){var t=new e.constructor(e.byteLength);return new Be(t).set(new Be(e)),t}function vo(e,t){var n=t?ho(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}function go(e,t){if(e!==t){var n=void 0!==e,r=null===e,o=e==e,i=Qa(e),a=void 0!==t,s=null===t,u=t==t,l=Qa(t);if(!s&&!l&&!i&&e>t||i&&a&&u&&!s&&!l||r&&a&&u||!n&&u||!o)return 1;if(!r&&!i&&!l&&e1?n[o-1]:void 0,a=o>2?n[2]:void 0;for(i=e.length>3&&"function"==typeof i?(o--,i):void 0,a&&li(n[0],n[1],a)&&(i=o<3?void 0:i,o=1),t=he(t);++r-1?o[i?t[a]:a]:void 0}}function jo(e){return Yo((function(t){var n=t.length,o=n,i=An.prototype.thru;for(e&&t.reverse();o--;){var a=t[o];if("function"!=typeof a)throw new me(r);if(i&&!s&&"wrapper"==Zo(a))var s=new An([],!0)}for(o=s?o:n;++o1&&y.reverse(),c&&us))return!1;var l=i.get(e),c=i.get(t);if(l&&c)return l==t&&c==e;var f=-1,d=!0,p=2&n?new Nn:void 0;for(i.set(e,t),i.set(t,e);++f-1&&e%1==0&&e1?"& ":"")+t[r],t=t.join(n>2?", ":" "),e.replace($,"{\n/* [wrapped with "+t+"] */\n")}(r,function(e,t){return it(i,(function(n){var r="_."+n[0];t&n[1]&&!lt(e,r)&&e.push(r)})),e.sort()}(function(e){var t=e.match(K);return t?t[1].split(Z):[]}(r),n)))}function Ci(e){var t=0,n=0;return function(){var r=ln(),o=16-(r-n);if(n=r,o>0){if(++t>=800)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function Oi(e,t){var n=-1,r=e.length,o=r-1;for(t=void 0===t?r:t;++n1?e[t-1]:void 0;return n="function"==typeof n?(e.pop(),n):void 0,Ki(e,n)}));function na(e){var t=jn(e);return t.__chain__=!0,t}function ra(e,t){return t(e)}var oa=Yo((function(e){var t=e.length,n=t?e[0]:0,r=this.__wrapped__,o=function(t){return Kn(t,e)};return!(t>1||this.__actions__.length)&&r instanceof Pn&&ui(n)?((r=r.slice(n,+n+(t?1:0))).__actions__.push({func:ra,args:[o],thisArg:void 0}),new An(r,this.__chain__).thru((function(e){return t&&!e.length&&e.push(void 0),e}))):this.thru(o)}));var ia=_o((function(e,t,n){ke.call(e,n)?++e[n]:$n(e,n,1)}));var aa=To(Pi),sa=To(Ri);function ua(e,t){return(Ra(e)?it:tr)(e,Qo(t,3))}function la(e,t){return(Ra(e)?at:nr)(e,Qo(t,3))}var ca=_o((function(e,t,n){ke.call(e,n)?e[n].push(t):$n(e,n,[t])}));var fa=Fr((function(e,t,n){var r=-1,o="function"==typeof t,i=Ia(e)?G(e.length):[];return tr(e,(function(e){i[++r]=o?rt(t,e,n):br(e,t,n)})),i})),da=_o((function(e,t,n){$n(e,n,t)}));function pa(e,t){return(Ra(e)?ft:Tr)(e,Qo(t,3))}var ha=_o((function(e,t,n){e[n?0:1].push(t)}),(function(){return[[],[]]}));var va=Fr((function(e,t){if(null==e)return[];var n=t.length;return n>1&&li(e,t[0],t[1])?t=[]:n>2&&li(t[0],t[1],t[2])&&(t=[t[0]]),Pr(e,ar(t,1),[])})),ga=Xt||function(){return qe.Date.now()};function ma(e,t,n){return t=n?void 0:t,Ho(e,128,void 0,void 0,void 0,void 0,t=e&&null==t?e.length:t)}function ya(e,t){var n;if("function"!=typeof t)throw new me(r);return e=os(e),function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=void 0),n}}var ba=Fr((function(e,t,n){var r=1;if(n.length){var o=Ht(n,Xo(ba));r|=32}return Ho(e,r,t,n,o)})),wa=Fr((function(e,t,n){var r=3;if(n.length){var o=Ht(n,Xo(wa));r|=32}return Ho(t,r,e,n,o)}));function _a(e,t,n){var o,i,a,s,u,l,c=0,f=!1,d=!1,p=!0;if("function"!=typeof e)throw new me(r);function h(t){var n=o,r=i;return o=i=void 0,c=t,s=e.apply(r,n)}function v(e){return c=e,u=_i(m,t),f?h(e):s}function g(e){var n=e-l;return void 0===l||n>=t||n<0||d&&e-c>=a}function m(){var e=ga();if(g(e))return y(e);u=_i(m,function(e){var n=t-(e-l);return d?un(n,a-(e-c)):n}(e))}function y(e){return u=void 0,p&&o?h(e):(o=i=void 0,s)}function b(){var e=ga(),n=g(e);if(o=arguments,i=this,l=e,n){if(void 0===u)return v(l);if(d)return fo(u),u=_i(m,t),h(l)}return void 0===u&&(u=_i(m,t)),s}return t=as(t)||0,Va(n)&&(f=!!n.leading,a=(d="maxWait"in n)?sn(as(n.maxWait)||0,t):a,p="trailing"in n?!!n.trailing:p),b.cancel=function(){void 0!==u&&fo(u),c=0,o=l=i=u=void 0},b.flush=function(){return void 0===u?s:y(ga())},b}var xa=Fr((function(e,t){return Jn(e,1,t)})),ka=Fr((function(e,t,n){return Jn(e,as(t)||0,n)}));function Ca(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new me(r);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=e.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(Ca.Cache||In),n}function Oa(e){if("function"!=typeof e)throw new me(r);return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}Ca.Cache=In;var Ea=lo((function(e,t){var n=(t=1==t.length&&Ra(t[0])?ft(t[0],jt(Qo())):ft(ar(t,1),jt(Qo()))).length;return Fr((function(r){for(var o=-1,i=un(r.length,n);++o=t})),Pa=wr(function(){return arguments}())?wr:function(e){return qa(e)&&ke.call(e,"callee")&&!Ge.call(e,"callee")},Ra=G.isArray,Da=Xe?jt(Xe):function(e){return qa(e)&&hr(e)==_};function Ia(e){return null!=e&&Wa(e.length)&&!Ha(e)}function Na(e){return qa(e)&&Ia(e)}var za=nn||au,Fa=Qe?jt(Qe):function(e){return qa(e)&&hr(e)==l};function Ba(e){if(!qa(e))return!1;var t=hr(e);return t==c||"[object DOMException]"==t||"string"==typeof e.message&&"string"==typeof e.name&&!$a(e)}function Ha(e){if(!Va(e))return!1;var t=hr(e);return t==f||t==d||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Ua(e){return"number"==typeof e&&e==os(e)}function Wa(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}function Va(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function qa(e){return null!=e&&"object"==typeof e}var Ya=Je?jt(Je):function(e){return qa(e)&&oi(e)==p};function Ga(e){return"number"==typeof e||qa(e)&&hr(e)==h}function $a(e){if(!qa(e)||hr(e)!=v)return!1;var t=Ve(e);if(null===t)return!0;var n=ke.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&xe.call(n)==Se}var Ka=et?jt(et):function(e){return qa(e)&&hr(e)==g};var Za=tt?jt(tt):function(e){return qa(e)&&oi(e)==m};function Xa(e){return"string"==typeof e||!Ra(e)&&qa(e)&&hr(e)==y}function Qa(e){return"symbol"==typeof e||qa(e)&&hr(e)==b}var Ja=nt?jt(nt):function(e){return qa(e)&&Wa(e.length)&&!!ze[hr(e)]};var es=Io(Sr),ts=Io((function(e,t){return e<=t}));function ns(e){if(!e)return[];if(Ia(e))return Xa(e)?qt(e):bo(e);if(gt&&e[gt])return function(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}(e[gt]());var t=oi(e);return(t==p?Ft:t==m?Ut:Ms)(e)}function rs(e){return e?(e=as(e))===1/0||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}function os(e){var t=rs(e),n=t%1;return t==t?n?t-n:t:0}function is(e){return e?Zn(os(e),0,4294967295):0}function as(e){if("number"==typeof e)return e;if(Qa(e))return NaN;if(Va(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Va(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=Tt(e);var n=re.test(e);return n||ie.test(e)?Ue(e.slice(2),n?2:8):ne.test(e)?NaN:+e}function ss(e){return wo(e,xs(e))}function us(e){return null==e?"":Qr(e)}var ls=xo((function(e,t){if(pi(t)||Ia(t))wo(t,_s(t),e);else for(var n in t)ke.call(t,n)&&Vn(e,n,t[n])})),cs=xo((function(e,t){wo(t,xs(t),e)})),fs=xo((function(e,t,n,r){wo(t,xs(t),e,r)})),ds=xo((function(e,t,n,r){wo(t,_s(t),e,r)})),ps=Yo(Kn);var hs=Fr((function(e,t){e=he(e);var n=-1,r=t.length,o=r>2?t[2]:void 0;for(o&&li(t[0],t[1],o)&&(r=1);++n1),t})),wo(e,$o(e),n),r&&(n=Xn(n,7,Vo));for(var o=t.length;o--;)eo(n,t[o]);return n}));var Es=Yo((function(e,t){return null==e?{}:function(e,t){return Rr(e,t,(function(t,n){return ms(e,n)}))}(e,t)}));function Ss(e,t){if(null==e)return{};var n=ft($o(e),(function(e){return[e]}));return t=Qo(t),Rr(e,n,(function(e,n){return t(e,n[0])}))}var Ts=Bo(_s),js=Bo(xs);function Ms(e){return null==e?[]:Mt(e,_s(e))}var Ls=Eo((function(e,t,n){return t=t.toLowerCase(),e+(n?As(t):t)}));function As(e){return Bs(us(e).toLowerCase())}function Ps(e){return(e=us(e))&&e.replace(se,Dt).replace(Le,"")}var Rs=Eo((function(e,t,n){return e+(n?"-":"")+t.toLowerCase()})),Ds=Eo((function(e,t,n){return e+(n?" ":"")+t.toLowerCase()})),Is=Oo("toLowerCase");var Ns=Eo((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));var zs=Eo((function(e,t,n){return e+(n?" ":"")+Bs(t)}));var Fs=Eo((function(e,t,n){return e+(n?" ":"")+t.toUpperCase()})),Bs=Oo("toUpperCase");function Hs(e,t,n){return e=us(e),void 0===(t=n?void 0:t)?function(e){return De.test(e)}(e)?function(e){return e.match(Pe)||[]}(e):function(e){return e.match(X)||[]}(e):e.match(t)||[]}var Us=Fr((function(e,t){try{return rt(e,void 0,t)}catch(e){return Ba(e)?e:new fe(e)}})),Ws=Yo((function(e,t){return it(t,(function(t){t=Si(t),$n(e,t,ba(e[t],e))})),e}));function Vs(e){return function(){return e}}var qs=jo(),Ys=jo(!0);function Gs(e){return e}function $s(e){return Cr("function"==typeof e?e:Xn(e,1))}var Ks=Fr((function(e,t){return function(n){return br(n,e,t)}})),Zs=Fr((function(e,t){return function(n){return br(e,n,t)}}));function Xs(e,t,n){var r=_s(t),o=fr(t,r);null!=n||Va(t)&&(o.length||!r.length)||(n=t,t=e,e=this,o=fr(t,_s(t)));var i=!(Va(n)&&"chain"in n&&!n.chain),a=Ha(e);return it(o,(function(n){var r=t[n];e[n]=r,a&&(e.prototype[n]=function(){var t=this.__chain__;if(i||t){var n=e(this.__wrapped__),o=n.__actions__=bo(this.__actions__);return o.push({func:r,args:arguments,thisArg:e}),n.__chain__=t,n}return r.apply(e,dt([this.value()],arguments))})})),e}function Qs(){}var Js=Po(ft),eu=Po(st),tu=Po(vt);function nu(e){return ci(e)?kt(Si(e)):function(e){return function(t){return dr(t,e)}}(e)}var ru=Do(),ou=Do(!0);function iu(){return[]}function au(){return!1}var su=Ao((function(e,t){return e+t}),0),uu=zo("ceil"),lu=Ao((function(e,t){return e/t}),1),cu=zo("floor");var fu,du=Ao((function(e,t){return e*t}),1),pu=zo("round"),hu=Ao((function(e,t){return e-t}),0);return jn.after=function(e,t){if("function"!=typeof t)throw new me(r);return e=os(e),function(){if(--e<1)return t.apply(this,arguments)}},jn.ary=ma,jn.assign=ls,jn.assignIn=cs,jn.assignInWith=fs,jn.assignWith=ds,jn.at=ps,jn.before=ya,jn.bind=ba,jn.bindAll=Ws,jn.bindKey=wa,jn.castArray=function(){if(!arguments.length)return[];var e=arguments[0];return Ra(e)?e:[e]},jn.chain=na,jn.chunk=function(e,t,n){t=(n?li(e,t,n):void 0===t)?1:sn(os(t),0);var r=null==e?0:e.length;if(!r||t<1)return[];for(var o=0,i=0,a=G(Jt(r/t));oo?0:o+n),(r=void 0===r||r>o?o:os(r))<0&&(r+=o),r=n>r?0:is(r);n>>0)?(e=us(e))&&("string"==typeof t||null!=t&&!Ka(t))&&!(t=Qr(t))&&zt(e)?co(qt(e),0,n):e.split(t,n):[]},jn.spread=function(e,t){if("function"!=typeof e)throw new me(r);return t=null==t?0:sn(os(t),0),Fr((function(n){var r=n[t],o=co(n,0,t);return r&&dt(o,r),rt(e,this,o)}))},jn.tail=function(e){var t=null==e?0:e.length;return t?Yr(e,1,t):[]},jn.take=function(e,t,n){return e&&e.length?Yr(e,0,(t=n||void 0===t?1:os(t))<0?0:t):[]},jn.takeRight=function(e,t,n){var r=null==e?0:e.length;return r?Yr(e,(t=r-(t=n||void 0===t?1:os(t)))<0?0:t,r):[]},jn.takeRightWhile=function(e,t){return e&&e.length?no(e,Qo(t,3),!1,!0):[]},jn.takeWhile=function(e,t){return e&&e.length?no(e,Qo(t,3)):[]},jn.tap=function(e,t){return t(e),e},jn.throttle=function(e,t,n){var o=!0,i=!0;if("function"!=typeof e)throw new me(r);return Va(n)&&(o="leading"in n?!!n.leading:o,i="trailing"in n?!!n.trailing:i),_a(e,t,{leading:o,maxWait:t,trailing:i})},jn.thru=ra,jn.toArray=ns,jn.toPairs=Ts,jn.toPairsIn=js,jn.toPath=function(e){return Ra(e)?ft(e,Si):Qa(e)?[e]:bo(Ei(us(e)))},jn.toPlainObject=ss,jn.transform=function(e,t,n){var r=Ra(e),o=r||za(e)||Ja(e);if(t=Qo(t,4),null==n){var i=e&&e.constructor;n=o?r?new i:[]:Va(e)&&Ha(i)?Mn(Ve(e)):{}}return(o?it:lr)(e,(function(e,r,o){return t(n,e,r,o)})),n},jn.unary=function(e){return ma(e,1)},jn.union=qi,jn.unionBy=Yi,jn.unionWith=Gi,jn.uniq=function(e){return e&&e.length?Jr(e):[]},jn.uniqBy=function(e,t){return e&&e.length?Jr(e,Qo(t,2)):[]},jn.uniqWith=function(e,t){return t="function"==typeof t?t:void 0,e&&e.length?Jr(e,void 0,t):[]},jn.unset=function(e,t){return null==e||eo(e,t)},jn.unzip=$i,jn.unzipWith=Ki,jn.update=function(e,t,n){return null==e?e:to(e,t,so(n))},jn.updateWith=function(e,t,n,r){return r="function"==typeof r?r:void 0,null==e?e:to(e,t,so(n),r)},jn.values=Ms,jn.valuesIn=function(e){return null==e?[]:Mt(e,xs(e))},jn.without=Zi,jn.words=Hs,jn.wrap=function(e,t){return Sa(so(t),e)},jn.xor=Xi,jn.xorBy=Qi,jn.xorWith=Ji,jn.zip=ea,jn.zipObject=function(e,t){return io(e||[],t||[],Vn)},jn.zipObjectDeep=function(e,t){return io(e||[],t||[],Ur)},jn.zipWith=ta,jn.entries=Ts,jn.entriesIn=js,jn.extend=cs,jn.extendWith=fs,Xs(jn,jn),jn.add=su,jn.attempt=Us,jn.camelCase=Ls,jn.capitalize=As,jn.ceil=uu,jn.clamp=function(e,t,n){return void 0===n&&(n=t,t=void 0),void 0!==n&&(n=(n=as(n))==n?n:0),void 0!==t&&(t=(t=as(t))==t?t:0),Zn(as(e),t,n)},jn.clone=function(e){return Xn(e,4)},jn.cloneDeep=function(e){return Xn(e,5)},jn.cloneDeepWith=function(e,t){return Xn(e,5,t="function"==typeof t?t:void 0)},jn.cloneWith=function(e,t){return Xn(e,4,t="function"==typeof t?t:void 0)},jn.conformsTo=function(e,t){return null==t||Qn(e,t,_s(t))},jn.deburr=Ps,jn.defaultTo=function(e,t){return null==e||e!=e?t:e},jn.divide=lu,jn.endsWith=function(e,t,n){e=us(e),t=Qr(t);var r=e.length,o=n=void 0===n?r:Zn(os(n),0,r);return(n-=t.length)>=0&&e.slice(n,o)==t},jn.eq=Ma,jn.escape=function(e){return(e=us(e))&&N.test(e)?e.replace(D,It):e},jn.escapeRegExp=function(e){return(e=us(e))&&q.test(e)?e.replace(V,"\\$&"):e},jn.every=function(e,t,n){var r=Ra(e)?st:rr;return n&&li(e,t,n)&&(t=void 0),r(e,Qo(t,3))},jn.find=aa,jn.findIndex=Pi,jn.findKey=function(e,t){return mt(e,Qo(t,3),lr)},jn.findLast=sa,jn.findLastIndex=Ri,jn.findLastKey=function(e,t){return mt(e,Qo(t,3),cr)},jn.floor=cu,jn.forEach=ua,jn.forEachRight=la,jn.forIn=function(e,t){return null==e?e:sr(e,Qo(t,3),xs)},jn.forInRight=function(e,t){return null==e?e:ur(e,Qo(t,3),xs)},jn.forOwn=function(e,t){return e&&lr(e,Qo(t,3))},jn.forOwnRight=function(e,t){return e&&cr(e,Qo(t,3))},jn.get=gs,jn.gt=La,jn.gte=Aa,jn.has=function(e,t){return null!=e&&ii(e,t,gr)},jn.hasIn=ms,jn.head=Ii,jn.identity=Gs,jn.includes=function(e,t,n,r){e=Ia(e)?e:Ms(e),n=n&&!r?os(n):0;var o=e.length;return n<0&&(n=sn(o+n,0)),Xa(e)?n<=o&&e.indexOf(t,n)>-1:!!o&&bt(e,t,n)>-1},jn.indexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=null==n?0:os(n);return o<0&&(o=sn(r+o,0)),bt(e,t,o)},jn.inRange=function(e,t,n){return t=rs(t),void 0===n?(n=t,t=0):n=rs(n),function(e,t,n){return e>=un(t,n)&&e=-9007199254740991&&e<=9007199254740991},jn.isSet=Za,jn.isString=Xa,jn.isSymbol=Qa,jn.isTypedArray=Ja,jn.isUndefined=function(e){return void 0===e},jn.isWeakMap=function(e){return qa(e)&&oi(e)==w},jn.isWeakSet=function(e){return qa(e)&&"[object WeakSet]"==hr(e)},jn.join=function(e,t){return null==e?"":on.call(e,t)},jn.kebabCase=Rs,jn.last=Bi,jn.lastIndexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=r;return void 0!==n&&(o=(o=os(n))<0?sn(r+o,0):un(o,r-1)),t==t?function(e,t,n){for(var r=n+1;r--;)if(e[r]===t)return r;return r}(e,t,o):yt(e,_t,o,!0)},jn.lowerCase=Ds,jn.lowerFirst=Is,jn.lt=es,jn.lte=ts,jn.max=function(e){return e&&e.length?or(e,Gs,vr):void 0},jn.maxBy=function(e,t){return e&&e.length?or(e,Qo(t,2),vr):void 0},jn.mean=function(e){return xt(e,Gs)},jn.meanBy=function(e,t){return xt(e,Qo(t,2))},jn.min=function(e){return e&&e.length?or(e,Gs,Sr):void 0},jn.minBy=function(e,t){return e&&e.length?or(e,Qo(t,2),Sr):void 0},jn.stubArray=iu,jn.stubFalse=au,jn.stubObject=function(){return{}},jn.stubString=function(){return""},jn.stubTrue=function(){return!0},jn.multiply=du,jn.nth=function(e,t){return e&&e.length?Ar(e,os(t)):void 0},jn.noConflict=function(){return qe._===this&&(qe._=Te),this},jn.noop=Qs,jn.now=ga,jn.pad=function(e,t,n){e=us(e);var r=(t=os(t))?Vt(e):0;if(!t||r>=t)return e;var o=(t-r)/2;return Ro(en(o),n)+e+Ro(Jt(o),n)},jn.padEnd=function(e,t,n){e=us(e);var r=(t=os(t))?Vt(e):0;return t&&rt){var r=e;e=t,t=r}if(n||e%1||t%1){var o=fn();return un(e+o*(t-e+He("1e-"+((o+"").length-1))),t)}return Nr(e,t)},jn.reduce=function(e,t,n){var r=Ra(e)?pt:Ot,o=arguments.length<3;return r(e,Qo(t,4),n,o,tr)},jn.reduceRight=function(e,t,n){var r=Ra(e)?ht:Ot,o=arguments.length<3;return r(e,Qo(t,4),n,o,nr)},jn.repeat=function(e,t,n){return t=(n?li(e,t,n):void 0===t)?1:os(t),zr(us(e),t)},jn.replace=function(){var e=arguments,t=us(e[0]);return e.length<3?t:t.replace(e[1],e[2])},jn.result=function(e,t,n){var r=-1,o=(t=uo(t,e)).length;for(o||(o=1,e=void 0);++r9007199254740991)return[];var n=4294967295,r=un(e,4294967295);e-=4294967295;for(var o=St(r,t=Qo(t));++n=i)return e;var s=n-Vt(r);if(s<1)return r;var u=a?co(a,0,s).join(""):e.slice(0,s);if(void 0===o)return u+r;if(a&&(s+=u.length-s),Ka(o)){if(e.slice(s).search(o)){var l,c=u;for(o.global||(o=ve(o.source,us(te.exec(o))+"g")),o.lastIndex=0;l=o.exec(c);)var f=l.index;u=u.slice(0,void 0===f?s:f)}}else if(e.indexOf(Qr(o),s)!=s){var d=u.lastIndexOf(o);d>-1&&(u=u.slice(0,d))}return u+r},jn.unescape=function(e){return(e=us(e))&&I.test(e)?e.replace(R,Gt):e},jn.uniqueId=function(e){var t=++Ce;return us(e)+t},jn.upperCase=Fs,jn.upperFirst=Bs,jn.each=ua,jn.eachRight=la,jn.first=Ii,Xs(jn,(fu={},lr(jn,(function(e,t){ke.call(jn.prototype,t)||(fu[t]=e)})),fu),{chain:!1}),jn.VERSION="4.17.21",it(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(e){jn[e].placeholder=jn})),it(["drop","take"],(function(e,t){Pn.prototype[e]=function(n){n=void 0===n?1:sn(os(n),0);var r=this.__filtered__&&!t?new Pn(this):this.clone();return r.__filtered__?r.__takeCount__=un(n,r.__takeCount__):r.__views__.push({size:un(n,4294967295),type:e+(r.__dir__<0?"Right":"")}),r},Pn.prototype[e+"Right"]=function(t){return this.reverse()[e](t).reverse()}})),it(["filter","map","takeWhile"],(function(e,t){var n=t+1,r=1==n||3==n;Pn.prototype[e]=function(e){var t=this.clone();return t.__iteratees__.push({iteratee:Qo(e,3),type:n}),t.__filtered__=t.__filtered__||r,t}})),it(["head","last"],(function(e,t){var n="take"+(t?"Right":"");Pn.prototype[e]=function(){return this[n](1).value()[0]}})),it(["initial","tail"],(function(e,t){var n="drop"+(t?"":"Right");Pn.prototype[e]=function(){return this.__filtered__?new Pn(this):this[n](1)}})),Pn.prototype.compact=function(){return this.filter(Gs)},Pn.prototype.find=function(e){return this.filter(e).head()},Pn.prototype.findLast=function(e){return this.reverse().find(e)},Pn.prototype.invokeMap=Fr((function(e,t){return"function"==typeof e?new Pn(this):this.map((function(n){return br(n,e,t)}))})),Pn.prototype.reject=function(e){return this.filter(Oa(Qo(e)))},Pn.prototype.slice=function(e,t){e=os(e);var n=this;return n.__filtered__&&(e>0||t<0)?new Pn(n):(e<0?n=n.takeRight(-e):e&&(n=n.drop(e)),void 0!==t&&(n=(t=os(t))<0?n.dropRight(-t):n.take(t-e)),n)},Pn.prototype.takeRightWhile=function(e){return this.reverse().takeWhile(e).reverse()},Pn.prototype.toArray=function(){return this.take(4294967295)},lr(Pn.prototype,(function(e,t){var n=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),o=jn[r?"take"+("last"==t?"Right":""):t],i=r||/^find/.test(t);o&&(jn.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,s=t instanceof Pn,u=a[0],l=s||Ra(t),c=function(e){var t=o.apply(jn,dt([e],a));return r&&f?t[0]:t};l&&n&&"function"==typeof u&&1!=u.length&&(s=l=!1);var f=this.__chain__,d=!!this.__actions__.length,p=i&&!f,h=s&&!d;if(!i&&l){t=h?t:new Pn(this);var v=e.apply(t,a);return v.__actions__.push({func:ra,args:[c],thisArg:void 0}),new An(v,f)}return p&&h?e.apply(this,a):(v=this.thru(c),p?r?v.value()[0]:v.value():v)})})),it(["pop","push","shift","sort","splice","unshift"],(function(e){var t=ye[e],n=/^(?:push|sort|unshift)$/.test(e)?"tap":"thru",r=/^(?:pop|shift)$/.test(e);jn.prototype[e]=function(){var e=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(Ra(o)?o:[],e)}return this[n]((function(n){return t.apply(Ra(n)?n:[],e)}))}})),lr(Pn.prototype,(function(e,t){var n=jn[t];if(n){var r=n.name+"";ke.call(wn,r)||(wn[r]=[]),wn[r].push({name:t,func:n})}})),wn[Mo(void 0,2).name]=[{name:"wrapper",func:void 0}],Pn.prototype.clone=function(){var e=new Pn(this.__wrapped__);return e.__actions__=bo(this.__actions__),e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=bo(this.__iteratees__),e.__takeCount__=this.__takeCount__,e.__views__=bo(this.__views__),e},Pn.prototype.reverse=function(){if(this.__filtered__){var e=new Pn(this);e.__dir__=-1,e.__filtered__=!0}else(e=this.clone()).__dir__*=-1;return e},Pn.prototype.value=function(){var e=this.__wrapped__.value(),t=this.__dir__,n=Ra(e),r=t<0,o=n?e.length:0,i=function(e,t,n){var r=-1,o=n.length;for(;++r=this.__values__.length;return{done:e,value:e?void 0:this.__values__[this.__index__++]}},jn.prototype.plant=function(e){for(var t,n=this;n instanceof Ln;){var r=ji(n);r.__index__=0,r.__values__=void 0,t?o.__wrapped__=r:t=r;var o=r;n=n.__wrapped__}return o.__wrapped__=e,t},jn.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof Pn){var t=e;return this.__actions__.length&&(t=new Pn(this)),(t=t.reverse()).__actions__.push({func:ra,args:[Vi],thisArg:void 0}),new An(t,this.__chain__)}return this.thru(Vi)},jn.prototype.toJSON=jn.prototype.valueOf=jn.prototype.value=function(){return ro(this.__wrapped__,this.__actions__)},jn.prototype.first=jn.prototype.head,gt&&(jn.prototype[gt]=function(){return this}),jn}();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(qe._=$t,define((function(){return $t}))):Ge?((Ge.exports=$t)._=$t,Ye._=$t):qe._=$t}).call(this)}).call(this,n(31),n(57)(e))},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){(function(e,n){(function(){var r="Expected a function",o="__lodash_placeholder__",i=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],a="[object Arguments]",s="[object Array]",u="[object Boolean]",l="[object Date]",c="[object Error]",f="[object Function]",d="[object GeneratorFunction]",p="[object Map]",h="[object Number]",v="[object Object]",g="[object RegExp]",m="[object Set]",y="[object String]",b="[object Symbol]",w="[object WeakMap]",_="[object ArrayBuffer]",x="[object DataView]",k="[object Float32Array]",C="[object Float64Array]",O="[object Int8Array]",E="[object Int16Array]",S="[object Int32Array]",T="[object Uint8Array]",j="[object Uint16Array]",M="[object Uint32Array]",L=/\b__p \+= '';/g,A=/\b(__p \+=) '' \+/g,P=/(__e\(.*?\)|\b__t\)) \+\n'';/g,R=/&(?:amp|lt|gt|quot|#39);/g,D=/[&<>"']/g,I=RegExp(R.source),N=RegExp(D.source),z=/<%-([\s\S]+?)%>/g,F=/<%([\s\S]+?)%>/g,B=/<%=([\s\S]+?)%>/g,H=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,U=/^\w*$/,W=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,V=/[\\^$.*+?()[\]{}|]/g,q=RegExp(V.source),Y=/^\s+/,G=/\s/,$=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,K=/\{\n\/\* \[wrapped with (.+)\] \*/,Z=/,? & /,X=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Q=/[()=,{}\[\]\/\s]/,J=/\\(\\)?/g,ee=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,te=/\w*$/,ne=/^[-+]0x[0-9a-f]+$/i,re=/^0b[01]+$/i,oe=/^\[object .+?Constructor\]$/,ie=/^0o[0-7]+$/i,ae=/^(?:0|[1-9]\d*)$/,se=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,ue=/($^)/,le=/['\n\r\u2028\u2029\\]/g,ce="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",fe="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",de="[\\ud800-\\udfff]",pe="["+fe+"]",he="["+ce+"]",ve="\\d+",ge="[\\u2700-\\u27bf]",me="[a-z\\xdf-\\xf6\\xf8-\\xff]",ye="[^\\ud800-\\udfff"+fe+ve+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",be="\\ud83c[\\udffb-\\udfff]",we="[^\\ud800-\\udfff]",_e="(?:\\ud83c[\\udde6-\\uddff]){2}",xe="[\\ud800-\\udbff][\\udc00-\\udfff]",ke="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Ce="(?:"+me+"|"+ye+")",Oe="(?:"+ke+"|"+ye+")",Ee="(?:"+he+"|"+be+")"+"?",Se="[\\ufe0e\\ufe0f]?"+Ee+("(?:\\u200d(?:"+[we,_e,xe].join("|")+")[\\ufe0e\\ufe0f]?"+Ee+")*"),Te="(?:"+[ge,_e,xe].join("|")+")"+Se,je="(?:"+[we+he+"?",he,_e,xe,de].join("|")+")",Me=RegExp("['\u2019]","g"),Le=RegExp(he,"g"),Ae=RegExp(be+"(?="+be+")|"+je+Se,"g"),Pe=RegExp([ke+"?"+me+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?(?="+[pe,ke,"$"].join("|")+")",Oe+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?(?="+[pe,ke+Ce,"$"].join("|")+")",ke+"?"+Ce+"+(?:['\u2019](?:d|ll|m|re|s|t|ve))?",ke+"+(?:['\u2019](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",ve,Te].join("|"),"g"),Re=RegExp("[\\u200d\\ud800-\\udfff"+ce+"\\ufe0e\\ufe0f]"),De=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Ie=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Ne=-1,ze={};ze[k]=ze[C]=ze[O]=ze[E]=ze[S]=ze[T]=ze["[object Uint8ClampedArray]"]=ze[j]=ze[M]=!0,ze[a]=ze[s]=ze[_]=ze[u]=ze[x]=ze[l]=ze[c]=ze[f]=ze[p]=ze[h]=ze[v]=ze[g]=ze[m]=ze[y]=ze[w]=!1;var Fe={};Fe[a]=Fe[s]=Fe[_]=Fe[x]=Fe[u]=Fe[l]=Fe[k]=Fe[C]=Fe[O]=Fe[E]=Fe[S]=Fe[p]=Fe[h]=Fe[v]=Fe[g]=Fe[m]=Fe[y]=Fe[b]=Fe[T]=Fe["[object Uint8ClampedArray]"]=Fe[j]=Fe[M]=!0,Fe[c]=Fe[f]=Fe[w]=!1;var Be={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},He=parseFloat,Ue=parseInt,We="object"==typeof e&&e&&e.Object===Object&&e,Ve="object"==typeof self&&self&&self.Object===Object&&self,qe=We||Ve||Function("return this")(),Ye=t&&!t.nodeType&&t,Ge=Ye&&"object"==typeof n&&n&&!n.nodeType&&n,$e=Ge&&Ge.exports===Ye,Ke=$e&&We.process,Ze=function(){try{var e=Ge&&Ge.require&&Ge.require("util").types;return e||Ke&&Ke.binding&&Ke.binding("util")}catch(e){}}(),Xe=Ze&&Ze.isArrayBuffer,Qe=Ze&&Ze.isDate,Je=Ze&&Ze.isMap,et=Ze&&Ze.isRegExp,tt=Ze&&Ze.isSet,nt=Ze&&Ze.isTypedArray;function rt(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function ot(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o-1}function ct(e,t,n){for(var r=-1,o=null==e?0:e.length;++r-1;);return n}function Pt(e,t){for(var n=e.length;n--&&bt(t,e[n],0)>-1;);return n}function Rt(e,t){for(var n=e.length,r=0;n--;)e[n]===t&&++r;return r}var Dt=Ct({"\xc0":"A","\xc1":"A","\xc2":"A","\xc3":"A","\xc4":"A","\xc5":"A","\xe0":"a","\xe1":"a","\xe2":"a","\xe3":"a","\xe4":"a","\xe5":"a","\xc7":"C","\xe7":"c","\xd0":"D","\xf0":"d","\xc8":"E","\xc9":"E","\xca":"E","\xcb":"E","\xe8":"e","\xe9":"e","\xea":"e","\xeb":"e","\xcc":"I","\xcd":"I","\xce":"I","\xcf":"I","\xec":"i","\xed":"i","\xee":"i","\xef":"i","\xd1":"N","\xf1":"n","\xd2":"O","\xd3":"O","\xd4":"O","\xd5":"O","\xd6":"O","\xd8":"O","\xf2":"o","\xf3":"o","\xf4":"o","\xf5":"o","\xf6":"o","\xf8":"o","\xd9":"U","\xda":"U","\xdb":"U","\xdc":"U","\xf9":"u","\xfa":"u","\xfb":"u","\xfc":"u","\xdd":"Y","\xfd":"y","\xff":"y","\xc6":"Ae","\xe6":"ae","\xde":"Th","\xfe":"th","\xdf":"ss","\u0100":"A","\u0102":"A","\u0104":"A","\u0101":"a","\u0103":"a","\u0105":"a","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\u010e":"D","\u0110":"D","\u010f":"d","\u0111":"d","\u0112":"E","\u0114":"E","\u0116":"E","\u0118":"E","\u011a":"E","\u0113":"e","\u0115":"e","\u0117":"e","\u0119":"e","\u011b":"e","\u011c":"G","\u011e":"G","\u0120":"G","\u0122":"G","\u011d":"g","\u011f":"g","\u0121":"g","\u0123":"g","\u0124":"H","\u0126":"H","\u0125":"h","\u0127":"h","\u0128":"I","\u012a":"I","\u012c":"I","\u012e":"I","\u0130":"I","\u0129":"i","\u012b":"i","\u012d":"i","\u012f":"i","\u0131":"i","\u0134":"J","\u0135":"j","\u0136":"K","\u0137":"k","\u0138":"k","\u0139":"L","\u013b":"L","\u013d":"L","\u013f":"L","\u0141":"L","\u013a":"l","\u013c":"l","\u013e":"l","\u0140":"l","\u0142":"l","\u0143":"N","\u0145":"N","\u0147":"N","\u014a":"N","\u0144":"n","\u0146":"n","\u0148":"n","\u014b":"n","\u014c":"O","\u014e":"O","\u0150":"O","\u014d":"o","\u014f":"o","\u0151":"o","\u0154":"R","\u0156":"R","\u0158":"R","\u0155":"r","\u0157":"r","\u0159":"r","\u015a":"S","\u015c":"S","\u015e":"S","\u0160":"S","\u015b":"s","\u015d":"s","\u015f":"s","\u0161":"s","\u0162":"T","\u0164":"T","\u0166":"T","\u0163":"t","\u0165":"t","\u0167":"t","\u0168":"U","\u016a":"U","\u016c":"U","\u016e":"U","\u0170":"U","\u0172":"U","\u0169":"u","\u016b":"u","\u016d":"u","\u016f":"u","\u0171":"u","\u0173":"u","\u0174":"W","\u0175":"w","\u0176":"Y","\u0177":"y","\u0178":"Y","\u0179":"Z","\u017b":"Z","\u017d":"Z","\u017a":"z","\u017c":"z","\u017e":"z","\u0132":"IJ","\u0133":"ij","\u0152":"Oe","\u0153":"oe","\u0149":"'n","\u017f":"s"}),It=Ct({"&":"&","<":"<",">":">",'"':""","'":"'"});function Nt(e){return"\\"+Be[e]}function zt(e){return Re.test(e)}function Ft(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}function Bt(e,t){return function(n){return e(t(n))}}function Ht(e,t){for(var n=-1,r=e.length,i=0,a=[];++n",""":'"',"'":"'"});var $t=function e(t){var n,G=(t=null==t?qe:$t.defaults(qe.Object(),t,$t.pick(qe,Ie))).Array,ce=t.Date,fe=t.Error,de=t.Function,pe=t.Math,he=t.Object,ve=t.RegExp,ge=t.String,me=t.TypeError,ye=G.prototype,be=de.prototype,we=he.prototype,_e=t["__core-js_shared__"],xe=be.toString,ke=we.hasOwnProperty,Ce=0,Oe=(n=/[^.]+$/.exec(_e&&_e.keys&&_e.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Ee=we.toString,Se=xe.call(he),Te=qe._,je=ve("^"+xe.call(ke).replace(V,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),Ae=$e?t.Buffer:void 0,Re=t.Symbol,Be=t.Uint8Array,We=Ae?Ae.allocUnsafe:void 0,Ve=Bt(he.getPrototypeOf,he),Ye=he.create,Ge=we.propertyIsEnumerable,Ke=ye.splice,Ze=Re?Re.isConcatSpreadable:void 0,gt=Re?Re.iterator:void 0,Ct=Re?Re.toStringTag:void 0,Kt=function(){try{var e=ti(he,"defineProperty");return e({},"",{}),e}catch(e){}}(),Zt=t.clearTimeout!==qe.clearTimeout&&t.clearTimeout,Xt=ce&&ce.now!==qe.Date.now&&ce.now,Qt=t.setTimeout!==qe.setTimeout&&t.setTimeout,Jt=pe.ceil,en=pe.floor,tn=he.getOwnPropertySymbols,nn=Ae?Ae.isBuffer:void 0,rn=t.isFinite,on=ye.join,an=Bt(he.keys,he),sn=pe.max,un=pe.min,ln=ce.now,cn=t.parseInt,fn=pe.random,dn=ye.reverse,pn=ti(t,"DataView"),hn=ti(t,"Map"),vn=ti(t,"Promise"),gn=ti(t,"Set"),mn=ti(t,"WeakMap"),yn=ti(he,"create"),bn=mn&&new mn,wn={},_n=Ti(pn),xn=Ti(hn),kn=Ti(vn),Cn=Ti(gn),On=Ti(mn),En=Re?Re.prototype:void 0,Sn=En?En.valueOf:void 0,Tn=En?En.toString:void 0;function jn(e){if(qa(e)&&!Ra(e)&&!(e instanceof Pn)){if(e instanceof An)return e;if(ke.call(e,"__wrapped__"))return ji(e)}return new An(e)}var Mn=function(){function e(){}return function(t){if(!Va(t))return{};if(Ye)return Ye(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();function Ln(){}function An(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=void 0}function Pn(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Rn(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=t?e:t)),e}function Xn(e,t,n,r,o,i){var s,c=1&t,w=2&t,L=4&t;if(n&&(s=o?n(e,r,o,i):n(e)),void 0!==s)return s;if(!Va(e))return e;var A=Ra(e);if(A){if(s=function(e){var t=e.length,n=new e.constructor(t);t&&"string"==typeof e[0]&&ke.call(e,"index")&&(n.index=e.index,n.input=e.input);return n}(e),!c)return bo(e,s)}else{var P=oi(e),R=P==f||P==d;if(za(e))return po(e,c);if(P==v||P==a||R&&!o){if(s=w||R?{}:ai(e),!c)return w?function(e,t){return wo(e,ri(e),t)}(e,function(e,t){return e&&wo(t,xs(t),e)}(s,e)):function(e,t){return wo(e,ni(e),t)}(e,Gn(s,e))}else{if(!Fe[P])return o?e:{};s=function(e,t,n){var r=e.constructor;switch(t){case _:return ho(e);case u:case l:return new r(+e);case x:return function(e,t){var n=t?ho(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}(e,n);case k:case C:case O:case E:case S:case T:case"[object Uint8ClampedArray]":case j:case M:return vo(e,n);case p:return new r;case h:case y:return new r(e);case g:return function(e){var t=new e.constructor(e.source,te.exec(e));return t.lastIndex=e.lastIndex,t}(e);case m:return new r;case b:return o=e,Sn?he(Sn.call(o)):{}}var o}(e,P,c)}}i||(i=new zn);var D=i.get(e);if(D)return D;i.set(e,s),Za(e)?e.forEach((function(r){s.add(Xn(r,t,n,r,e,i))})):Ya(e)&&e.forEach((function(r,o){s.set(o,Xn(r,t,n,o,e,i))}));var I=A?void 0:(L?w?$o:Go:w?xs:_s)(e);return it(I||e,(function(r,o){I&&(r=e[o=r]),Vn(s,o,Xn(r,t,n,o,e,i))})),s}function Qn(e,t,n){var r=n.length;if(null==e)return!r;for(e=he(e);r--;){var o=n[r],i=t[o],a=e[o];if(void 0===a&&!(o in e)||!i(a))return!1}return!0}function Jn(e,t,n){if("function"!=typeof e)throw new me(r);return _i((function(){e.apply(void 0,n)}),t)}function er(e,t,n,r){var o=-1,i=lt,a=!0,s=e.length,u=[],l=t.length;if(!s)return u;n&&(t=ft(t,jt(n))),r?(i=ct,a=!1):t.length>=200&&(i=Lt,a=!1,t=new Nn(t));e:for(;++o-1},Dn.prototype.set=function(e,t){var n=this.__data__,r=qn(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},In.prototype.clear=function(){this.size=0,this.__data__={hash:new Rn,map:new(hn||Dn),string:new Rn}},In.prototype.delete=function(e){var t=Jo(this,e).delete(e);return this.size-=t?1:0,t},In.prototype.get=function(e){return Jo(this,e).get(e)},In.prototype.has=function(e){return Jo(this,e).has(e)},In.prototype.set=function(e,t){var n=Jo(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},Nn.prototype.add=Nn.prototype.push=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this},Nn.prototype.has=function(e){return this.__data__.has(e)},zn.prototype.clear=function(){this.__data__=new Dn,this.size=0},zn.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},zn.prototype.get=function(e){return this.__data__.get(e)},zn.prototype.has=function(e){return this.__data__.has(e)},zn.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Dn){var r=n.__data__;if(!hn||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new In(r)}return n.set(e,t),this.size=n.size,this};var tr=ko(lr),nr=ko(cr,!0);function rr(e,t){var n=!0;return tr(e,(function(e,r,o){return n=!!t(e,r,o)})),n}function or(e,t,n){for(var r=-1,o=e.length;++r0&&n(s)?t>1?ar(s,t-1,n,r,o):dt(o,s):r||(o[o.length]=s)}return o}var sr=Co(),ur=Co(!0);function lr(e,t){return e&&sr(e,t,_s)}function cr(e,t){return e&&ur(e,t,_s)}function fr(e,t){return ut(t,(function(t){return Ha(e[t])}))}function dr(e,t){for(var n=0,r=(t=uo(t,e)).length;null!=e&&nt}function gr(e,t){return null!=e&&ke.call(e,t)}function mr(e,t){return null!=e&&t in he(e)}function yr(e,t,n){for(var r=n?ct:lt,o=e[0].length,i=e.length,a=i,s=G(i),u=1/0,l=[];a--;){var c=e[a];a&&t&&(c=ft(c,jt(t))),u=un(c.length,u),s[a]=!n&&(t||o>=120&&c.length>=120)?new Nn(a&&c):void 0}c=e[0];var f=-1,d=s[0];e:for(;++f=s)return u;var l=n[r];return u*("desc"==l?-1:1)}}return e.index-t.index}(e,t,n)}))}function Rr(e,t,n){for(var r=-1,o=t.length,i={};++r-1;)s!==e&&Ke.call(s,u,1),Ke.call(e,u,1);return e}function Ir(e,t){for(var n=e?t.length:0,r=n-1;n--;){var o=t[n];if(n==r||o!==i){var i=o;ui(o)?Ke.call(e,o,1):eo(e,o)}}return e}function Nr(e,t){return e+en(fn()*(t-e+1))}function zr(e,t){var n="";if(!e||t<1||t>9007199254740991)return n;do{t%2&&(n+=e),(t=en(t/2))&&(e+=e)}while(t);return n}function Fr(e,t){return xi(gi(e,t,Gs),e+"")}function Br(e){return Bn(Ms(e))}function Hr(e,t){var n=Ms(e);return Oi(n,Zn(t,0,n.length))}function Ur(e,t,n,r){if(!Va(e))return e;for(var o=-1,i=(t=uo(t,e)).length,a=i-1,s=e;null!=s&&++oo?0:o+t),(n=n>o?o:n)<0&&(n+=o),o=t>n?0:n-t>>>0,t>>>=0;for(var i=G(o);++r>>1,a=e[i];null!==a&&!Qa(a)&&(n?a<=t:a=200){var l=t?null:Fo(e);if(l)return Ut(l);a=!1,o=Lt,u=new Nn}else u=t?[]:s;e:for(;++r=r?e:Yr(e,t,n)}var fo=Zt||function(e){return qe.clearTimeout(e)};function po(e,t){if(t)return e.slice();var n=e.length,r=We?We(n):new e.constructor(n);return e.copy(r),r}function ho(e){var t=new e.constructor(e.byteLength);return new Be(t).set(new Be(e)),t}function vo(e,t){var n=t?ho(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}function go(e,t){if(e!==t){var n=void 0!==e,r=null===e,o=e==e,i=Qa(e),a=void 0!==t,s=null===t,u=t==t,l=Qa(t);if(!s&&!l&&!i&&e>t||i&&a&&u&&!s&&!l||r&&a&&u||!n&&u||!o)return 1;if(!r&&!i&&!l&&e1?n[o-1]:void 0,a=o>2?n[2]:void 0;for(i=e.length>3&&"function"==typeof i?(o--,i):void 0,a&&li(n[0],n[1],a)&&(i=o<3?void 0:i,o=1),t=he(t);++r-1?o[i?t[a]:a]:void 0}}function jo(e){return Yo((function(t){var n=t.length,o=n,i=An.prototype.thru;for(e&&t.reverse();o--;){var a=t[o];if("function"!=typeof a)throw new me(r);if(i&&!s&&"wrapper"==Zo(a))var s=new An([],!0)}for(o=s?o:n;++o1&&y.reverse(),c&&us))return!1;var l=i.get(e),c=i.get(t);if(l&&c)return l==t&&c==e;var f=-1,d=!0,p=2&n?new Nn:void 0;for(i.set(e,t),i.set(t,e);++f-1&&e%1==0&&e1?"& ":"")+t[r],t=t.join(n>2?", ":" "),e.replace($,"{\n/* [wrapped with "+t+"] */\n")}(r,function(e,t){return it(i,(function(n){var r="_."+n[0];t&n[1]&&!lt(e,r)&&e.push(r)})),e.sort()}(function(e){var t=e.match(K);return t?t[1].split(Z):[]}(r),n)))}function Ci(e){var t=0,n=0;return function(){var r=ln(),o=16-(r-n);if(n=r,o>0){if(++t>=800)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function Oi(e,t){var n=-1,r=e.length,o=r-1;for(t=void 0===t?r:t;++n1?e[t-1]:void 0;return n="function"==typeof n?(e.pop(),n):void 0,Ki(e,n)}));function na(e){var t=jn(e);return t.__chain__=!0,t}function ra(e,t){return t(e)}var oa=Yo((function(e){var t=e.length,n=t?e[0]:0,r=this.__wrapped__,o=function(t){return Kn(t,e)};return!(t>1||this.__actions__.length)&&r instanceof Pn&&ui(n)?((r=r.slice(n,+n+(t?1:0))).__actions__.push({func:ra,args:[o],thisArg:void 0}),new An(r,this.__chain__).thru((function(e){return t&&!e.length&&e.push(void 0),e}))):this.thru(o)}));var ia=_o((function(e,t,n){ke.call(e,n)?++e[n]:$n(e,n,1)}));var aa=To(Pi),sa=To(Ri);function ua(e,t){return(Ra(e)?it:tr)(e,Qo(t,3))}function la(e,t){return(Ra(e)?at:nr)(e,Qo(t,3))}var ca=_o((function(e,t,n){ke.call(e,n)?e[n].push(t):$n(e,n,[t])}));var fa=Fr((function(e,t,n){var r=-1,o="function"==typeof t,i=Ia(e)?G(e.length):[];return tr(e,(function(e){i[++r]=o?rt(t,e,n):br(e,t,n)})),i})),da=_o((function(e,t,n){$n(e,n,t)}));function pa(e,t){return(Ra(e)?ft:Tr)(e,Qo(t,3))}var ha=_o((function(e,t,n){e[n?0:1].push(t)}),(function(){return[[],[]]}));var va=Fr((function(e,t){if(null==e)return[];var n=t.length;return n>1&&li(e,t[0],t[1])?t=[]:n>2&&li(t[0],t[1],t[2])&&(t=[t[0]]),Pr(e,ar(t,1),[])})),ga=Xt||function(){return qe.Date.now()};function ma(e,t,n){return t=n?void 0:t,Ho(e,128,void 0,void 0,void 0,void 0,t=e&&null==t?e.length:t)}function ya(e,t){var n;if("function"!=typeof t)throw new me(r);return e=os(e),function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=void 0),n}}var ba=Fr((function(e,t,n){var r=1;if(n.length){var o=Ht(n,Xo(ba));r|=32}return Ho(e,r,t,n,o)})),wa=Fr((function(e,t,n){var r=3;if(n.length){var o=Ht(n,Xo(wa));r|=32}return Ho(t,r,e,n,o)}));function _a(e,t,n){var o,i,a,s,u,l,c=0,f=!1,d=!1,p=!0;if("function"!=typeof e)throw new me(r);function h(t){var n=o,r=i;return o=i=void 0,c=t,s=e.apply(r,n)}function v(e){return c=e,u=_i(m,t),f?h(e):s}function g(e){var n=e-l;return void 0===l||n>=t||n<0||d&&e-c>=a}function m(){var e=ga();if(g(e))return y(e);u=_i(m,function(e){var n=t-(e-l);return d?un(n,a-(e-c)):n}(e))}function y(e){return u=void 0,p&&o?h(e):(o=i=void 0,s)}function b(){var e=ga(),n=g(e);if(o=arguments,i=this,l=e,n){if(void 0===u)return v(l);if(d)return fo(u),u=_i(m,t),h(l)}return void 0===u&&(u=_i(m,t)),s}return t=as(t)||0,Va(n)&&(f=!!n.leading,a=(d="maxWait"in n)?sn(as(n.maxWait)||0,t):a,p="trailing"in n?!!n.trailing:p),b.cancel=function(){void 0!==u&&fo(u),c=0,o=l=i=u=void 0},b.flush=function(){return void 0===u?s:y(ga())},b}var xa=Fr((function(e,t){return Jn(e,1,t)})),ka=Fr((function(e,t,n){return Jn(e,as(t)||0,n)}));function Ca(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new me(r);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=e.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(Ca.Cache||In),n}function Oa(e){if("function"!=typeof e)throw new me(r);return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}Ca.Cache=In;var Ea=lo((function(e,t){var n=(t=1==t.length&&Ra(t[0])?ft(t[0],jt(Qo())):ft(ar(t,1),jt(Qo()))).length;return Fr((function(r){for(var o=-1,i=un(r.length,n);++o=t})),Pa=wr(function(){return arguments}())?wr:function(e){return qa(e)&&ke.call(e,"callee")&&!Ge.call(e,"callee")},Ra=G.isArray,Da=Xe?jt(Xe):function(e){return qa(e)&&hr(e)==_};function Ia(e){return null!=e&&Wa(e.length)&&!Ha(e)}function Na(e){return qa(e)&&Ia(e)}var za=nn||au,Fa=Qe?jt(Qe):function(e){return qa(e)&&hr(e)==l};function Ba(e){if(!qa(e))return!1;var t=hr(e);return t==c||"[object DOMException]"==t||"string"==typeof e.message&&"string"==typeof e.name&&!$a(e)}function Ha(e){if(!Va(e))return!1;var t=hr(e);return t==f||t==d||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Ua(e){return"number"==typeof e&&e==os(e)}function Wa(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}function Va(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function qa(e){return null!=e&&"object"==typeof e}var Ya=Je?jt(Je):function(e){return qa(e)&&oi(e)==p};function Ga(e){return"number"==typeof e||qa(e)&&hr(e)==h}function $a(e){if(!qa(e)||hr(e)!=v)return!1;var t=Ve(e);if(null===t)return!0;var n=ke.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&xe.call(n)==Se}var Ka=et?jt(et):function(e){return qa(e)&&hr(e)==g};var Za=tt?jt(tt):function(e){return qa(e)&&oi(e)==m};function Xa(e){return"string"==typeof e||!Ra(e)&&qa(e)&&hr(e)==y}function Qa(e){return"symbol"==typeof e||qa(e)&&hr(e)==b}var Ja=nt?jt(nt):function(e){return qa(e)&&Wa(e.length)&&!!ze[hr(e)]};var es=Io(Sr),ts=Io((function(e,t){return e<=t}));function ns(e){if(!e)return[];if(Ia(e))return Xa(e)?qt(e):bo(e);if(gt&&e[gt])return function(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}(e[gt]());var t=oi(e);return(t==p?Ft:t==m?Ut:Ms)(e)}function rs(e){return e?(e=as(e))===1/0||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}function os(e){var t=rs(e),n=t%1;return t==t?n?t-n:t:0}function is(e){return e?Zn(os(e),0,4294967295):0}function as(e){if("number"==typeof e)return e;if(Qa(e))return NaN;if(Va(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Va(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=Tt(e);var n=re.test(e);return n||ie.test(e)?Ue(e.slice(2),n?2:8):ne.test(e)?NaN:+e}function ss(e){return wo(e,xs(e))}function us(e){return null==e?"":Qr(e)}var ls=xo((function(e,t){if(pi(t)||Ia(t))wo(t,_s(t),e);else for(var n in t)ke.call(t,n)&&Vn(e,n,t[n])})),cs=xo((function(e,t){wo(t,xs(t),e)})),fs=xo((function(e,t,n,r){wo(t,xs(t),e,r)})),ds=xo((function(e,t,n,r){wo(t,_s(t),e,r)})),ps=Yo(Kn);var hs=Fr((function(e,t){e=he(e);var n=-1,r=t.length,o=r>2?t[2]:void 0;for(o&&li(t[0],t[1],o)&&(r=1);++n1),t})),wo(e,$o(e),n),r&&(n=Xn(n,7,Vo));for(var o=t.length;o--;)eo(n,t[o]);return n}));var Es=Yo((function(e,t){return null==e?{}:function(e,t){return Rr(e,t,(function(t,n){return ms(e,n)}))}(e,t)}));function Ss(e,t){if(null==e)return{};var n=ft($o(e),(function(e){return[e]}));return t=Qo(t),Rr(e,n,(function(e,n){return t(e,n[0])}))}var Ts=Bo(_s),js=Bo(xs);function Ms(e){return null==e?[]:Mt(e,_s(e))}var Ls=Eo((function(e,t,n){return t=t.toLowerCase(),e+(n?As(t):t)}));function As(e){return Bs(us(e).toLowerCase())}function Ps(e){return(e=us(e))&&e.replace(se,Dt).replace(Le,"")}var Rs=Eo((function(e,t,n){return e+(n?"-":"")+t.toLowerCase()})),Ds=Eo((function(e,t,n){return e+(n?" ":"")+t.toLowerCase()})),Is=Oo("toLowerCase");var Ns=Eo((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));var zs=Eo((function(e,t,n){return e+(n?" ":"")+Bs(t)}));var Fs=Eo((function(e,t,n){return e+(n?" ":"")+t.toUpperCase()})),Bs=Oo("toUpperCase");function Hs(e,t,n){return e=us(e),void 0===(t=n?void 0:t)?function(e){return De.test(e)}(e)?function(e){return e.match(Pe)||[]}(e):function(e){return e.match(X)||[]}(e):e.match(t)||[]}var Us=Fr((function(e,t){try{return rt(e,void 0,t)}catch(e){return Ba(e)?e:new fe(e)}})),Ws=Yo((function(e,t){return it(t,(function(t){t=Si(t),$n(e,t,ba(e[t],e))})),e}));function Vs(e){return function(){return e}}var qs=jo(),Ys=jo(!0);function Gs(e){return e}function $s(e){return Cr("function"==typeof e?e:Xn(e,1))}var Ks=Fr((function(e,t){return function(n){return br(n,e,t)}})),Zs=Fr((function(e,t){return function(n){return br(e,n,t)}}));function Xs(e,t,n){var r=_s(t),o=fr(t,r);null!=n||Va(t)&&(o.length||!r.length)||(n=t,t=e,e=this,o=fr(t,_s(t)));var i=!(Va(n)&&"chain"in n&&!n.chain),a=Ha(e);return it(o,(function(n){var r=t[n];e[n]=r,a&&(e.prototype[n]=function(){var t=this.__chain__;if(i||t){var n=e(this.__wrapped__),o=n.__actions__=bo(this.__actions__);return o.push({func:r,args:arguments,thisArg:e}),n.__chain__=t,n}return r.apply(e,dt([this.value()],arguments))})})),e}function Qs(){}var Js=Po(ft),eu=Po(st),tu=Po(vt);function nu(e){return ci(e)?kt(Si(e)):function(e){return function(t){return dr(t,e)}}(e)}var ru=Do(),ou=Do(!0);function iu(){return[]}function au(){return!1}var su=Ao((function(e,t){return e+t}),0),uu=zo("ceil"),lu=Ao((function(e,t){return e/t}),1),cu=zo("floor");var fu,du=Ao((function(e,t){return e*t}),1),pu=zo("round"),hu=Ao((function(e,t){return e-t}),0);return jn.after=function(e,t){if("function"!=typeof t)throw new me(r);return e=os(e),function(){if(--e<1)return t.apply(this,arguments)}},jn.ary=ma,jn.assign=ls,jn.assignIn=cs,jn.assignInWith=fs,jn.assignWith=ds,jn.at=ps,jn.before=ya,jn.bind=ba,jn.bindAll=Ws,jn.bindKey=wa,jn.castArray=function(){if(!arguments.length)return[];var e=arguments[0];return Ra(e)?e:[e]},jn.chain=na,jn.chunk=function(e,t,n){t=(n?li(e,t,n):void 0===t)?1:sn(os(t),0);var r=null==e?0:e.length;if(!r||t<1)return[];for(var o=0,i=0,a=G(Jt(r/t));oo?0:o+n),(r=void 0===r||r>o?o:os(r))<0&&(r+=o),r=n>r?0:is(r);n>>0)?(e=us(e))&&("string"==typeof t||null!=t&&!Ka(t))&&!(t=Qr(t))&&zt(e)?co(qt(e),0,n):e.split(t,n):[]},jn.spread=function(e,t){if("function"!=typeof e)throw new me(r);return t=null==t?0:sn(os(t),0),Fr((function(n){var r=n[t],o=co(n,0,t);return r&&dt(o,r),rt(e,this,o)}))},jn.tail=function(e){var t=null==e?0:e.length;return t?Yr(e,1,t):[]},jn.take=function(e,t,n){return e&&e.length?Yr(e,0,(t=n||void 0===t?1:os(t))<0?0:t):[]},jn.takeRight=function(e,t,n){var r=null==e?0:e.length;return r?Yr(e,(t=r-(t=n||void 0===t?1:os(t)))<0?0:t,r):[]},jn.takeRightWhile=function(e,t){return e&&e.length?no(e,Qo(t,3),!1,!0):[]},jn.takeWhile=function(e,t){return e&&e.length?no(e,Qo(t,3)):[]},jn.tap=function(e,t){return t(e),e},jn.throttle=function(e,t,n){var o=!0,i=!0;if("function"!=typeof e)throw new me(r);return Va(n)&&(o="leading"in n?!!n.leading:o,i="trailing"in n?!!n.trailing:i),_a(e,t,{leading:o,maxWait:t,trailing:i})},jn.thru=ra,jn.toArray=ns,jn.toPairs=Ts,jn.toPairsIn=js,jn.toPath=function(e){return Ra(e)?ft(e,Si):Qa(e)?[e]:bo(Ei(us(e)))},jn.toPlainObject=ss,jn.transform=function(e,t,n){var r=Ra(e),o=r||za(e)||Ja(e);if(t=Qo(t,4),null==n){var i=e&&e.constructor;n=o?r?new i:[]:Va(e)&&Ha(i)?Mn(Ve(e)):{}}return(o?it:lr)(e,(function(e,r,o){return t(n,e,r,o)})),n},jn.unary=function(e){return ma(e,1)},jn.union=qi,jn.unionBy=Yi,jn.unionWith=Gi,jn.uniq=function(e){return e&&e.length?Jr(e):[]},jn.uniqBy=function(e,t){return e&&e.length?Jr(e,Qo(t,2)):[]},jn.uniqWith=function(e,t){return t="function"==typeof t?t:void 0,e&&e.length?Jr(e,void 0,t):[]},jn.unset=function(e,t){return null==e||eo(e,t)},jn.unzip=$i,jn.unzipWith=Ki,jn.update=function(e,t,n){return null==e?e:to(e,t,so(n))},jn.updateWith=function(e,t,n,r){return r="function"==typeof r?r:void 0,null==e?e:to(e,t,so(n),r)},jn.values=Ms,jn.valuesIn=function(e){return null==e?[]:Mt(e,xs(e))},jn.without=Zi,jn.words=Hs,jn.wrap=function(e,t){return Sa(so(t),e)},jn.xor=Xi,jn.xorBy=Qi,jn.xorWith=Ji,jn.zip=ea,jn.zipObject=function(e,t){return io(e||[],t||[],Vn)},jn.zipObjectDeep=function(e,t){return io(e||[],t||[],Ur)},jn.zipWith=ta,jn.entries=Ts,jn.entriesIn=js,jn.extend=cs,jn.extendWith=fs,Xs(jn,jn),jn.add=su,jn.attempt=Us,jn.camelCase=Ls,jn.capitalize=As,jn.ceil=uu,jn.clamp=function(e,t,n){return void 0===n&&(n=t,t=void 0),void 0!==n&&(n=(n=as(n))==n?n:0),void 0!==t&&(t=(t=as(t))==t?t:0),Zn(as(e),t,n)},jn.clone=function(e){return Xn(e,4)},jn.cloneDeep=function(e){return Xn(e,5)},jn.cloneDeepWith=function(e,t){return Xn(e,5,t="function"==typeof t?t:void 0)},jn.cloneWith=function(e,t){return Xn(e,4,t="function"==typeof t?t:void 0)},jn.conformsTo=function(e,t){return null==t||Qn(e,t,_s(t))},jn.deburr=Ps,jn.defaultTo=function(e,t){return null==e||e!=e?t:e},jn.divide=lu,jn.endsWith=function(e,t,n){e=us(e),t=Qr(t);var r=e.length,o=n=void 0===n?r:Zn(os(n),0,r);return(n-=t.length)>=0&&e.slice(n,o)==t},jn.eq=Ma,jn.escape=function(e){return(e=us(e))&&N.test(e)?e.replace(D,It):e},jn.escapeRegExp=function(e){return(e=us(e))&&q.test(e)?e.replace(V,"\\$&"):e},jn.every=function(e,t,n){var r=Ra(e)?st:rr;return n&&li(e,t,n)&&(t=void 0),r(e,Qo(t,3))},jn.find=aa,jn.findIndex=Pi,jn.findKey=function(e,t){return mt(e,Qo(t,3),lr)},jn.findLast=sa,jn.findLastIndex=Ri,jn.findLastKey=function(e,t){return mt(e,Qo(t,3),cr)},jn.floor=cu,jn.forEach=ua,jn.forEachRight=la,jn.forIn=function(e,t){return null==e?e:sr(e,Qo(t,3),xs)},jn.forInRight=function(e,t){return null==e?e:ur(e,Qo(t,3),xs)},jn.forOwn=function(e,t){return e&&lr(e,Qo(t,3))},jn.forOwnRight=function(e,t){return e&&cr(e,Qo(t,3))},jn.get=gs,jn.gt=La,jn.gte=Aa,jn.has=function(e,t){return null!=e&&ii(e,t,gr)},jn.hasIn=ms,jn.head=Ii,jn.identity=Gs,jn.includes=function(e,t,n,r){e=Ia(e)?e:Ms(e),n=n&&!r?os(n):0;var o=e.length;return n<0&&(n=sn(o+n,0)),Xa(e)?n<=o&&e.indexOf(t,n)>-1:!!o&&bt(e,t,n)>-1},jn.indexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=null==n?0:os(n);return o<0&&(o=sn(r+o,0)),bt(e,t,o)},jn.inRange=function(e,t,n){return t=rs(t),void 0===n?(n=t,t=0):n=rs(n),function(e,t,n){return e>=un(t,n)&&e=-9007199254740991&&e<=9007199254740991},jn.isSet=Za,jn.isString=Xa,jn.isSymbol=Qa,jn.isTypedArray=Ja,jn.isUndefined=function(e){return void 0===e},jn.isWeakMap=function(e){return qa(e)&&oi(e)==w},jn.isWeakSet=function(e){return qa(e)&&"[object WeakSet]"==hr(e)},jn.join=function(e,t){return null==e?"":on.call(e,t)},jn.kebabCase=Rs,jn.last=Bi,jn.lastIndexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=r;return void 0!==n&&(o=(o=os(n))<0?sn(r+o,0):un(o,r-1)),t==t?function(e,t,n){for(var r=n+1;r--;)if(e[r]===t)return r;return r}(e,t,o):yt(e,_t,o,!0)},jn.lowerCase=Ds,jn.lowerFirst=Is,jn.lt=es,jn.lte=ts,jn.max=function(e){return e&&e.length?or(e,Gs,vr):void 0},jn.maxBy=function(e,t){return e&&e.length?or(e,Qo(t,2),vr):void 0},jn.mean=function(e){return xt(e,Gs)},jn.meanBy=function(e,t){return xt(e,Qo(t,2))},jn.min=function(e){return e&&e.length?or(e,Gs,Sr):void 0},jn.minBy=function(e,t){return e&&e.length?or(e,Qo(t,2),Sr):void 0},jn.stubArray=iu,jn.stubFalse=au,jn.stubObject=function(){return{}},jn.stubString=function(){return""},jn.stubTrue=function(){return!0},jn.multiply=du,jn.nth=function(e,t){return e&&e.length?Ar(e,os(t)):void 0},jn.noConflict=function(){return qe._===this&&(qe._=Te),this},jn.noop=Qs,jn.now=ga,jn.pad=function(e,t,n){e=us(e);var r=(t=os(t))?Vt(e):0;if(!t||r>=t)return e;var o=(t-r)/2;return Ro(en(o),n)+e+Ro(Jt(o),n)},jn.padEnd=function(e,t,n){e=us(e);var r=(t=os(t))?Vt(e):0;return t&&rt){var r=e;e=t,t=r}if(n||e%1||t%1){var o=fn();return un(e+o*(t-e+He("1e-"+((o+"").length-1))),t)}return Nr(e,t)},jn.reduce=function(e,t,n){var r=Ra(e)?pt:Ot,o=arguments.length<3;return r(e,Qo(t,4),n,o,tr)},jn.reduceRight=function(e,t,n){var r=Ra(e)?ht:Ot,o=arguments.length<3;return r(e,Qo(t,4),n,o,nr)},jn.repeat=function(e,t,n){return t=(n?li(e,t,n):void 0===t)?1:os(t),zr(us(e),t)},jn.replace=function(){var e=arguments,t=us(e[0]);return e.length<3?t:t.replace(e[1],e[2])},jn.result=function(e,t,n){var r=-1,o=(t=uo(t,e)).length;for(o||(o=1,e=void 0);++r9007199254740991)return[];var n=4294967295,r=un(e,4294967295);e-=4294967295;for(var o=St(r,t=Qo(t));++n=i)return e;var s=n-Vt(r);if(s<1)return r;var u=a?co(a,0,s).join(""):e.slice(0,s);if(void 0===o)return u+r;if(a&&(s+=u.length-s),Ka(o)){if(e.slice(s).search(o)){var l,c=u;for(o.global||(o=ve(o.source,us(te.exec(o))+"g")),o.lastIndex=0;l=o.exec(c);)var f=l.index;u=u.slice(0,void 0===f?s:f)}}else if(e.indexOf(Qr(o),s)!=s){var d=u.lastIndexOf(o);d>-1&&(u=u.slice(0,d))}return u+r},jn.unescape=function(e){return(e=us(e))&&I.test(e)?e.replace(R,Gt):e},jn.uniqueId=function(e){var t=++Ce;return us(e)+t},jn.upperCase=Fs,jn.upperFirst=Bs,jn.each=ua,jn.eachRight=la,jn.first=Ii,Xs(jn,(fu={},lr(jn,(function(e,t){ke.call(jn.prototype,t)||(fu[t]=e)})),fu),{chain:!1}),jn.VERSION="4.17.21",it(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(e){jn[e].placeholder=jn})),it(["drop","take"],(function(e,t){Pn.prototype[e]=function(n){n=void 0===n?1:sn(os(n),0);var r=this.__filtered__&&!t?new Pn(this):this.clone();return r.__filtered__?r.__takeCount__=un(n,r.__takeCount__):r.__views__.push({size:un(n,4294967295),type:e+(r.__dir__<0?"Right":"")}),r},Pn.prototype[e+"Right"]=function(t){return this.reverse()[e](t).reverse()}})),it(["filter","map","takeWhile"],(function(e,t){var n=t+1,r=1==n||3==n;Pn.prototype[e]=function(e){var t=this.clone();return t.__iteratees__.push({iteratee:Qo(e,3),type:n}),t.__filtered__=t.__filtered__||r,t}})),it(["head","last"],(function(e,t){var n="take"+(t?"Right":"");Pn.prototype[e]=function(){return this[n](1).value()[0]}})),it(["initial","tail"],(function(e,t){var n="drop"+(t?"":"Right");Pn.prototype[e]=function(){return this.__filtered__?new Pn(this):this[n](1)}})),Pn.prototype.compact=function(){return this.filter(Gs)},Pn.prototype.find=function(e){return this.filter(e).head()},Pn.prototype.findLast=function(e){return this.reverse().find(e)},Pn.prototype.invokeMap=Fr((function(e,t){return"function"==typeof e?new Pn(this):this.map((function(n){return br(n,e,t)}))})),Pn.prototype.reject=function(e){return this.filter(Oa(Qo(e)))},Pn.prototype.slice=function(e,t){e=os(e);var n=this;return n.__filtered__&&(e>0||t<0)?new Pn(n):(e<0?n=n.takeRight(-e):e&&(n=n.drop(e)),void 0!==t&&(n=(t=os(t))<0?n.dropRight(-t):n.take(t-e)),n)},Pn.prototype.takeRightWhile=function(e){return this.reverse().takeWhile(e).reverse()},Pn.prototype.toArray=function(){return this.take(4294967295)},lr(Pn.prototype,(function(e,t){var n=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),o=jn[r?"take"+("last"==t?"Right":""):t],i=r||/^find/.test(t);o&&(jn.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,s=t instanceof Pn,u=a[0],l=s||Ra(t),c=function(e){var t=o.apply(jn,dt([e],a));return r&&f?t[0]:t};l&&n&&"function"==typeof u&&1!=u.length&&(s=l=!1);var f=this.__chain__,d=!!this.__actions__.length,p=i&&!f,h=s&&!d;if(!i&&l){t=h?t:new Pn(this);var v=e.apply(t,a);return v.__actions__.push({func:ra,args:[c],thisArg:void 0}),new An(v,f)}return p&&h?e.apply(this,a):(v=this.thru(c),p?r?v.value()[0]:v.value():v)})})),it(["pop","push","shift","sort","splice","unshift"],(function(e){var t=ye[e],n=/^(?:push|sort|unshift)$/.test(e)?"tap":"thru",r=/^(?:pop|shift)$/.test(e);jn.prototype[e]=function(){var e=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(Ra(o)?o:[],e)}return this[n]((function(n){return t.apply(Ra(n)?n:[],e)}))}})),lr(Pn.prototype,(function(e,t){var n=jn[t];if(n){var r=n.name+"";ke.call(wn,r)||(wn[r]=[]),wn[r].push({name:t,func:n})}})),wn[Mo(void 0,2).name]=[{name:"wrapper",func:void 0}],Pn.prototype.clone=function(){var e=new Pn(this.__wrapped__);return e.__actions__=bo(this.__actions__),e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=bo(this.__iteratees__),e.__takeCount__=this.__takeCount__,e.__views__=bo(this.__views__),e},Pn.prototype.reverse=function(){if(this.__filtered__){var e=new Pn(this);e.__dir__=-1,e.__filtered__=!0}else(e=this.clone()).__dir__*=-1;return e},Pn.prototype.value=function(){var e=this.__wrapped__.value(),t=this.__dir__,n=Ra(e),r=t<0,o=n?e.length:0,i=function(e,t,n){var r=-1,o=n.length;for(;++r=this.__values__.length;return{done:e,value:e?void 0:this.__values__[this.__index__++]}},jn.prototype.plant=function(e){for(var t,n=this;n instanceof Ln;){var r=ji(n);r.__index__=0,r.__values__=void 0,t?o.__wrapped__=r:t=r;var o=r;n=n.__wrapped__}return o.__wrapped__=e,t},jn.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof Pn){var t=e;return this.__actions__.length&&(t=new Pn(this)),(t=t.reverse()).__actions__.push({func:ra,args:[Vi],thisArg:void 0}),new An(t,this.__chain__)}return this.thru(Vi)},jn.prototype.toJSON=jn.prototype.valueOf=jn.prototype.value=function(){return ro(this.__wrapped__,this.__actions__)},jn.prototype.first=jn.prototype.head,gt&&(jn.prototype[gt]=function(){return this}),jn}();"function"==typeof define&&"object"==typeof define.amd&&define.amd?(qe._=$t,define((function(){return $t}))):Ge?((Ge.exports=$t)._=$t,Ye._=$t):qe._=$t}).call(this)}).call(this,n(31),n(57)(e))},function(e,t){e.exports=function(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},e.exports.__esModule=!0,e.exports.default=e.exports,n(t)}e.exports=n,e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){var r=n(73).default,o=n(7);e.exports=function(e,t){if(t&&("object"==r(t)||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return o(e)},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t,n){"use strict";n.d(t,"a",(function(){return s})),n.d(t,"j",(function(){return Q})),n.d(t,"h",(function(){return J})),n.d(t,"f",(function(){return X})),n.d(t,"b",(function(){return P})),n.d(t,"g",(function(){return N})),n.d(t,"i",(function(){return F})),n.d(t,"c",(function(){return I})),n.d(t,"e",(function(){return U})),n.d(t,"d",(function(){return H}));var r=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{},r=n.wrap,o=void 0===r||r,i=n.ignoreDefinition,a=void 0!==i&&i;A(this,e),this.definition=t,"function"!=typeof t&&(a||this.verifyDefinition(t),this.wrap=o,this.ProviderConstructor=function(e){this.context=e},this.ProviderConstructor.prototype=t,this.WrappedProviderConstructor=function(e,t){this.context=t,this.providerName=e},this.WrappedProviderConstructor.prototype=Object.keys(a?{}:t).reduce((function(e,n){var r=t[n];return e[n]=function(){for(var e=this,t=arguments.length,o=Array(t),i=0;i0&&void 0===e)throw new Error('Cannot extract value at path "'+t+'" ("'+n+'" is not defined).');return e[n]}),e)}var z=function(e){function t(e){D(this,t);var n=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));return n.cvalue=e,n}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),R(t,[{key:"getValue",value:function(e){var t=e.resolve,n=this.cvalue;return t.isResolveValue(n)?t.value(n):Object.keys(n).reduce((function(e,r){return e[r]=t.value(n[r]),e}),{})}}]),t}(I),F=function(e){return new z(e)},B=function(){function e(e,t){for(var n=0;n1?r-1:0),i=1;i1?t-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:{};return e instanceof I?e.getValue(t?Object.assign({},this.context,t):this.context):e},path:function(e){if(e instanceof H)return e.getPath(this.context);throw new Error("You are extracting a path from an argument that is not a Tag.")}},{wrap:!1}),V=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{},n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};G(this,t);var r=Y(this,(t.__proto__||Object.getPrototypeOf(t)).call(this));if(r.cachedTrees=[],r.cachedStaticTrees=[],r.executeBranchWrapper=n.executeBranchWrapper||function(e){e()},"object"!==(void 0===e?"undefined":q(e))||null===e||Array.isArray(e))throw new Error("You have to pass an object of context providers to FunctionTree");var o=Object.keys(e);if(o.indexOf("props")>=0||o.indexOf("path")>=0||o.indexOf("resolve")>=0||o.indexOf("execution")>=0||o.indexOf("debugger")>=0)throw new Error('You are trying to add a provider with protected key. "props", "path", "resolve", "execution" and "debugger" are protected');return r.contextProviders=Object.assign({},e,{resolve:W}),r.run=r.run.bind(r),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),V(t,[{key:"run",value:function(){var e=this,t=void 0,n=void 0,r=void 0,o=void 0,i=void 0,a=[].slice.call(arguments);if(a.forEach((function(e){"string"==typeof e?t=e:Array.isArray(e)||e instanceof s?n=e:n||"function"!=typeof e?"function"==typeof e?o=e:r=e:n=e})),!n)throw new Error("function-tree - You did not pass in a function tree");var u=function(o,a){var s=e.cachedTrees.indexOf(n);-1===s?(i=w(t,n),e.cachedTrees.push(n),e.cachedStaticTrees.push(i)):i=e.cachedStaticTrees[s];var u=new Z(t,i,e,(function(t,n,r,o){e.emit("error",t,n,r,o),a(t)}));e.emit("start",u,r),E(u,r,e.executeBranchWrapper,(function(t,n,r){e.emit("pathStart",n,u,t,r)}),(function(t){e.emit("pathEnd",u,t)}),(function(t,n){e.emit("parallelStart",u,t,n)}),(function(t,n){e.emit("parallelProgress",u,t,n)}),(function(t,n){e.emit("parallelEnd",u,t,n)}),(function(t){e.emit("end",u,t),o===a?o(null,t):o(t)}))};if(!o)return new Promise(u);u(o,o)}}]),t}(C.a);function Q(){for(var e=arguments.length,t=Array(e),n=0;n2),m=/Android/.test(e),y=g||m||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),b=g||/Mac/.test(t),w=/\bCrOS\b/.test(e),_=/win/i.test(t),x=d&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(d=!1,u=!0);var k=b&&(l||d&&(null==x||x<12.11)),C=n||a&&s>=9;function O(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var E,S=function(e,t){var n=e.className,r=O(t).exec(n);if(r){var o=n.slice(r.index+r[0].length);e.className=n.slice(0,r.index)+(o?r[1]+o:"")}};function T(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function j(e,t){return T(e).appendChild(t)}function M(e,t,n,r){var o=document.createElement(e);if(n&&(o.className=n),r&&(o.style.cssText=r),"string"==typeof t)o.appendChild(document.createTextNode(t));else if(t)for(var i=0;i=t)return a+(t-i);a+=s-i,a+=n-a%n,i=s+1}}g?I=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:a&&(I=function(e){try{e.select()}catch(e){}});var B=function(){this.id=null,this.f=null,this.time=0,this.handler=N(this.onTimeout,this)};function H(e,t){for(var n=0;n=t)return r+Math.min(a,t-o);if(o+=i-r,r=i+1,(o+=n-o%n)>=t)return r}}var G=[""];function $(e){for(;G.length<=e;)G.push(K(G)+" ");return G[e]}function K(e){return e[e.length-1]}function Z(e,t){for(var n=[],r=0;r"\x80"&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ee(e))||t.test(e):ee(e)}function ne(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var re=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function oe(e){return e.charCodeAt(0)>=768&&re.test(e)}function ie(e,t,n){for(;(n<0?t>0:tn?-1:1;;){if(t==n)return t;var o=(t+n)/2,i=r<0?Math.ceil(o):Math.floor(o);if(i==t)return e(i)?t:n;e(i)?n=i:t=i+r}}var se=null;function ue(e,t,n){var r;se=null;for(var o=0;ot)return o;i.to==t&&(i.from!=i.to&&"before"==n?r=o:se=o),i.from==t&&(i.from!=i.to&&"before"!=n?r=o:se=o)}return null!=r?r:se}var le=function(){var e=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,t=/[stwN]/,n=/[LRr]/,r=/[Lb1n]/,o=/[1n]/;function i(e,t,n){this.level=e,this.from=t,this.to=n}return function(a,s){var u="ltr"==s?"L":"R";if(0==a.length||"ltr"==s&&!e.test(a))return!1;for(var l,c=a.length,f=[],d=0;d-1&&(r[t]=o.slice(0,i).concat(o.slice(i+1)))}}}function ve(e,t){var n=pe(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),o=0;o0}function be(e){e.prototype.on=function(e,t){de(this,e,t)},e.prototype.off=function(e,t){he(this,e,t)}}function we(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function _e(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function xe(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function ke(e){we(e),_e(e)}function Ce(e){return e.target||e.srcElement}function Oe(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),b&&e.ctrlKey&&1==t&&(t=3),t}var Ee,Se,Te=function(){if(a&&s<9)return!1;var e=M("div");return"draggable"in e||"dragDrop"in e}();function je(e){if(null==Ee){var t=M("span","\u200b");j(e,M("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Ee=t.offsetWidth<=1&&t.offsetHeight>2&&!(a&&s<8))}var n=Ee?M("span","\u200b"):M("span","\xa0",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}function Me(e){if(null!=Se)return Se;var t=j(e,document.createTextNode("A\u062eA")),n=E(t,0,1).getBoundingClientRect(),r=E(t,1,2).getBoundingClientRect();return T(e),!(!n||n.left==n.right)&&(Se=r.right-n.right<3)}var Le,Ae=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var o=e.indexOf("\n",t);-1==o&&(o=e.length);var i=e.slice(t,"\r"==e.charAt(o-1)?o-1:o),a=i.indexOf("\r");-1!=a?(n.push(i.slice(0,a)),t+=a+1):(n.push(i),t=o+1)}return n}:function(e){return e.split(/\r\n?|\n/)},Pe=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Re="oncopy"in(Le=M("div"))||(Le.setAttribute("oncopy","return;"),"function"==typeof Le.oncopy),De=null,Ie={},Ne={};function ze(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ie[e]=t}function Fe(e){if("string"==typeof e&&Ne.hasOwnProperty(e))e=Ne[e];else if(e&&"string"==typeof e.name&&Ne.hasOwnProperty(e.name)){var t=Ne[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Fe("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Fe("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Be(e,t){t=Fe(t);var n=Ie[t.name];if(!n)return Be(e,"text/plain");var r=n(e,t);if(He.hasOwnProperty(t.name)){var o=He[t.name];for(var i in o)o.hasOwnProperty(i)&&(r.hasOwnProperty(i)&&(r["_"+i]=r[i]),r[i]=o[i])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var a in t.modeProps)r[a]=t.modeProps[a];return r}var He={};function Ue(e,t){z(t,He.hasOwnProperty(e)?He[e]:He[e]={})}function We(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var o=t[r];o instanceof Array&&(o=o.concat([])),n[r]=o}return n}function Ve(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function qe(e,t,n){return!e.startState||e.startState(t,n)}var Ye=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function Ge(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var o=n.children[r],i=o.chunkSize();if(t=e.first&&tn?tt(n,Ge(e,n).text.length):function(e,t){var n=e.ch;return null==n||n>t?tt(e.line,t):n<0?tt(e.line,0):e}(t,Ge(e,t.line).text.length)}function lt(e,t){for(var n=[],r=0;r=this.string.length},Ye.prototype.sol=function(){return this.pos==this.lineStart},Ye.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Ye.prototype.next=function(){if(this.post},Ye.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Ye.prototype.skipToEnd=function(){this.pos=this.string.length},Ye.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},Ye.prototype.backUp=function(e){this.pos-=e},Ye.prototype.column=function(){return this.lastColumnPos0?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}var o=function(e){return n?e.toLowerCase():e};if(o(this.string.substr(this.pos,e.length))==o(e))return!1!==t&&(this.pos+=e.length),!0},Ye.prototype.current=function(){return this.string.slice(this.start,this.pos)},Ye.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Ye.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Ye.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var ct=function(e,t){this.state=e,this.lookAhead=t},ft=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function dt(e,t,n,r){var o=[e.state.modeGen],i={};_t(e,t.text,e.doc.mode,n,(function(e,t){return o.push(e,t)}),i,r);for(var a=n.state,s=function(r){n.baseTokens=o;var s=e.state.overlays[r],u=1,l=0;n.state=!0,_t(e,t.text,s.mode,n,(function(e,t){for(var n=u;le&&o.splice(u,1,e,o[u+1],r),u+=2,l=Math.min(e,r)}if(t)if(s.opaque)o.splice(n,u-n,e,"overlay "+t),u=n+2;else for(;ne.options.maxHighlightLength&&We(e.doc.mode,r.state),i=dt(e,t,r);o&&(r.state=o),t.stateAfter=r.save(!o),t.styles=i.styles,i.classes?t.styleClasses=i.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function ht(e,t,n){var r=e.doc,o=e.display;if(!r.mode.startState)return new ft(r,!0,t);var i=function(e,t,n){for(var r,o,i=e.doc,a=n?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>a;--s){if(s<=i.first)return i.first;var u=Ge(i,s-1),l=u.stateAfter;if(l&&(!n||s+(l instanceof ct?l.lookAhead:0)<=i.modeFrontier))return s;var c=F(u.text,null,e.options.tabSize);(null==o||r>c)&&(o=s-1,r=c)}return o}(e,t,n),a=i>r.first&&Ge(r,i-1).stateAfter,s=a?ft.fromSaved(r,a,i):new ft(r,qe(r.mode),i);return r.iter(i,t,(function(n){vt(e,n.text,s);var r=s.line;n.stateAfter=r==t-1||r%5==0||r>=o.viewFrom&&rt.start)return i}throw new Error("Mode "+e.name+" failed to advance stream.")}ft.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ft.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ft.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},ft.fromSaved=function(e,t,n){return t instanceof ct?new ft(e,We(e.mode,t.state),n,t.lookAhead):new ft(e,We(e.mode,t),n)},ft.prototype.save=function(e){var t=!1!==e?We(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new ct(t,this.maxLookAhead):t};var yt=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function bt(e,t,n,r){var o,i,a=e.doc,s=a.mode,u=Ge(a,(t=ut(a,t)).line),l=ht(e,t.line,n),c=new Ye(u.text,e.options.tabSize,l);for(r&&(i=[]);(r||c.pose.options.maxHighlightLength?(s=!1,a&&vt(e,t,r,f.pos),f.pos=t.length,u=null):u=wt(mt(n,f,r.state,d),i),d){var p=d[0].name;p&&(u="m-"+(u?p+" "+u:p))}if(!s||c!=u){for(;l=t:i.to>t);(r||(r=[])).push(new Ct(a,i.from,s?null:i.to))}}return r}(n,o,a),u=function(e,t,n){var r;if(e)for(var o=0;o=t:i.to>t)||i.from==t&&"bookmark"==a.type&&(!n||i.marker.insertLeft)){var s=null==i.from||(a.inclusiveLeft?i.from<=t:i.from0&&s)for(var b=0;bt)&&(!n||Pt(n,i.marker)<0)&&(n=i.marker)}return n}function zt(e,t,n,r,o){var i=Ge(e,t),a=kt&&i.markedSpans;if(a)for(var s=0;s=0&&f<=0||c<=0&&f>=0)&&(c<=0&&(u.marker.inclusiveRight&&o.inclusiveLeft?nt(l.to,n)>=0:nt(l.to,n)>0)||c>=0&&(u.marker.inclusiveRight&&o.inclusiveLeft?nt(l.from,r)<=0:nt(l.from,r)<0)))return!0}}}function Ft(e){for(var t;t=Dt(e);)e=t.find(-1,!0).line;return e}function Bt(e,t){var n=Ge(e,t),r=Ft(n);return n==r?t:Xe(r)}function Ht(e,t){if(t>e.lastLine())return t;var n,r=Ge(e,t);if(!Ut(e,r))return t;for(;n=It(r);)r=n.find(1,!0).line;return Xe(r)+1}function Ut(e,t){var n=kt&&t.markedSpans;if(n)for(var r=void 0,o=0;ot.maxLineLength&&(t.maxLineLength=n,t.maxLine=e)}))}var Gt=function(e,t,n){this.text=e,Mt(this,t),this.height=n?n(this):1};function $t(e){e.parent=null,jt(e)}Gt.prototype.lineNo=function(){return Xe(this)},be(Gt);var Kt={},Zt={};function Xt(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?Zt:Kt;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function Qt(e,t){var n=L("span",null,null,u?"padding-right: .1px":null),r={pre:L("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var o=0;o<=(t.rest?t.rest.length:0);o++){var i=o?t.rest[o-1]:t.line,a=void 0;r.pos=0,r.addToken=en,Me(e.display.measure)&&(a=ce(i,e.doc.direction))&&(r.addToken=tn(r.addToken,a)),r.map=[],rn(i,r,pt(e,i,t!=e.display.externalMeasured&&Xe(i))),i.styleClasses&&(i.styleClasses.bgClass&&(r.bgClass=D(i.styleClasses.bgClass,r.bgClass||"")),i.styleClasses.textClass&&(r.textClass=D(i.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(je(e.display.measure))),0==o?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(u){var s=r.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")}return ve(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=D(r.pre.className,r.textClass||"")),r}function Jt(e){var t=M("span","\u2022","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function en(e,t,n,r,o,i,u){if(t){var l,c=e.splitSpaces?function(e,t){if(e.length>1&&!/ /.test(e))return e;for(var n=t,r="",o=0;ol&&f.from<=l);d++);if(f.to>=c)return e(n,r,o,i,a,s,u);e(n,r.slice(0,f.to-l),o,i,null,s,u),i=null,r=r.slice(f.to-l),l=f.to}}}function nn(e,t,n,r){var o=!r&&n.widgetNode;o&&e.map.push(e.pos,e.pos+t,o),!r&&e.cm.display.input.needsContentAttribute&&(o||(o=e.content.appendChild(document.createElement("span"))),o.setAttribute("cm-marker",n.id)),o&&(e.cm.display.input.setUneditable(o),e.content.appendChild(o)),e.pos+=t,e.trailingSpace=!1}function rn(e,t,n){var r=e.markedSpans,o=e.text,i=0;if(r)for(var a,s,u,l,c,f,d,p=o.length,h=0,v=1,g="",m=0;;){if(m==h){u=l=c=s="",d=null,f=null,m=1/0;for(var y=[],b=void 0,w=0;wh||x.collapsed&&_.to==h&&_.from==h)){if(null!=_.to&&_.to!=h&&m>_.to&&(m=_.to,l=""),x.className&&(u+=" "+x.className),x.css&&(s=(s?s+";":"")+x.css),x.startStyle&&_.from==h&&(c+=" "+x.startStyle),x.endStyle&&_.to==m&&(b||(b=[])).push(x.endStyle,_.to),x.title&&((d||(d={})).title=x.title),x.attributes)for(var k in x.attributes)(d||(d={}))[k]=x.attributes[k];x.collapsed&&(!f||Pt(f.marker,x)<0)&&(f=_)}else _.from>h&&m>_.from&&(m=_.from)}if(b)for(var C=0;C=p)break;for(var E=Math.min(p,m);;){if(g){var S=h+g.length;if(!f){var T=S>E?g.slice(0,E-h):g;t.addToken(t,T,a?a+u:u,c,h+T.length==m?l:"",s,d)}if(S>=E){g=g.slice(E-h),h=E;break}h=S,c=""}g=o.slice(i,i=n[v++]),a=Xt(n[v++],t.cm.options)}}else for(var j=1;jn)return{map:e.measure.maps[o],cache:e.measure.caches[o],before:!0}}}function Ln(e,t,n,r){return Rn(e,Pn(e,t),n,r)}function An(e,t){if(t>=e.display.viewFrom&&t=n.lineN&&t2&&i.push((u.bottom+l.top)/2-n.top)}}i.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),(i=function(e,t,n,r){var o,i=Nn(t.map,n,r),u=i.node,l=i.start,c=i.end,f=i.collapse;if(3==u.nodeType){for(var d=0;d<4;d++){for(;l&&oe(t.line.text.charAt(i.coverStart+l));)--l;for(;i.coverStart+c1}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,r=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*r,bottom:t.bottom*r}}(e.display.measure,o))}else{var p;l>0&&(f=r="right"),o=e.options.lineWrapping&&(p=u.getClientRects()).length>1?p["right"==r?p.length-1:0]:u.getBoundingClientRect()}if(a&&s<9&&!l&&(!o||!o.left&&!o.right)){var h=u.parentNode.getClientRects()[0];o=h?{left:h.left,right:h.left+ir(e.display),top:h.top,bottom:h.bottom}:In}for(var v=o.top-t.rect.top,g=o.bottom-t.rect.top,m=(v+g)/2,y=t.view.measure.heights,b=0;bt)&&(o=(i=u-s)-1,t>=u&&(a="right")),null!=o){if(r=e[l+2],s==u&&n==(r.insertLeft?"left":"right")&&(a=n),"left"==n&&0==o)for(;l&&e[l-2]==e[l-3]&&e[l-1].insertLeft;)r=e[2+(l-=3)],a="left";if("right"==n&&o==u-s)for(;l=0&&(n=e[o]).left==n.right;o--);return n}function Fn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t=r.text.length?(u=r.text.length,l="before"):u<=0&&(u=0,l="after"),!s)return a("before"==l?u-1:u,"before"==l);function c(e,t,n){return a(n?e-1:e,1==s[t].level!=n)}var f=ue(s,u,l),d=se,p=c(u,f,"before"==l);return null!=d&&(p.other=c(u,d,"before"!=l)),p}function Kn(e,t){var n=0;t=ut(e.doc,t),e.options.lineWrapping||(n=ir(e.display)*t.ch);var r=Ge(e.doc,t.line),o=Vt(r)+Cn(e.display);return{left:n,right:n,top:o,bottom:o+r.height}}function Zn(e,t,n,r,o){var i=tt(e,t,n);return i.xRel=o,r&&(i.outside=r),i}function Xn(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return Zn(r.first,0,null,-1,-1);var o=Qe(r,n),i=r.first+r.size-1;if(o>i)return Zn(r.first+r.size-1,Ge(r,i).text.length,null,1,1);t<0&&(t=0);for(var a=Ge(r,o);;){var s=tr(e,a,o,t,n),u=Nt(a,s.ch+(s.xRel>0||s.outside>0?1:0));if(!u)return s;var l=u.find(1);if(l.line==o)return l;a=Ge(r,o=l.line)}}function Qn(e,t,n,r){r-=Vn(t);var o=t.text.length,i=ae((function(t){return Rn(e,n,t-1).bottom<=r}),o,0);return{begin:i,end:o=ae((function(t){return Rn(e,n,t).top>r}),i,o)}}function Jn(e,t,n,r){return n||(n=Pn(e,t)),Qn(e,t,n,qn(e,t,Rn(e,n,r),"line").top)}function er(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function tr(e,t,n,r,o){o-=Vt(t);var i=Pn(e,t),a=Vn(t),s=0,u=t.text.length,l=!0,c=ce(t,e.doc.direction);if(c){var f=(e.options.lineWrapping?rr:nr)(e,t,n,i,c,r,o);s=(l=1!=f.level)?f.from:f.to-1,u=l?f.to:f.from-1}var d,p,h=null,v=null,g=ae((function(t){var n=Rn(e,i,t);return n.top+=a,n.bottom+=a,!!er(n,r,o,!1)&&(n.top<=o&&n.left<=r&&(h=t,v=n),!0)}),s,u),m=!1;if(v){var y=r-v.left=w.bottom?1:0}return Zn(n,g=ie(t.text,g,1),p,m,r-d)}function nr(e,t,n,r,o,i,a){var s=ae((function(s){var u=o[s],l=1!=u.level;return er($n(e,tt(n,l?u.to:u.from,l?"before":"after"),"line",t,r),i,a,!0)}),0,o.length-1),u=o[s];if(s>0){var l=1!=u.level,c=$n(e,tt(n,l?u.from:u.to,l?"after":"before"),"line",t,r);er(c,i,a,!0)&&c.top>a&&(u=o[s-1])}return u}function rr(e,t,n,r,o,i,a){var s=Qn(e,t,r,a),u=s.begin,l=s.end;/\s/.test(t.text.charAt(l-1))&&l--;for(var c=null,f=null,d=0;d=l||p.to<=u)){var h=Rn(e,r,1!=p.level?Math.min(l,p.to)-1:Math.max(u,p.from)).right,v=hv)&&(c=p,f=v)}}return c||(c=o[o.length-1]),c.froml&&(c={from:c.from,to:l,level:c.level}),c}function or(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Dn){Dn=M("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Dn.appendChild(document.createTextNode("x")),Dn.appendChild(M("br"));Dn.appendChild(document.createTextNode("x"))}j(e.measure,Dn);var n=Dn.offsetHeight/50;return n>3&&(e.cachedTextHeight=n),T(e.measure),n||1}function ir(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=M("span","xxxxxxxxxx"),n=M("pre",[t],"CodeMirror-line-like");j(e.measure,n);var r=t.getBoundingClientRect(),o=(r.right-r.left)/10;return o>2&&(e.cachedCharWidth=o),o||10}function ar(e){for(var t=e.display,n={},r={},o=t.gutters.clientLeft,i=t.gutters.firstChild,a=0;i;i=i.nextSibling,++a){var s=e.display.gutterSpecs[a].className;n[s]=i.offsetLeft+i.clientLeft+o,r[s]=i.clientWidth}return{fixedPos:sr(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function sr(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function ur(e){var t=or(e.display),n=e.options.lineWrapping,r=n&&Math.max(5,e.display.scroller.clientWidth/ir(e.display)-3);return function(o){if(Ut(e.doc,o))return 0;var i=0;if(o.widgets)for(var a=0;a0&&(u=Ge(e.doc,l.line).text).length==l.ch){var c=F(u,u.length,e.options.tabSize)-u.length;l=tt(l.line,Math.max(0,Math.round((i-En(e.display).left)/ir(e.display))-c))}return l}function fr(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;rt)&&(o.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=o.viewTo)kt&&Bt(e.doc,t)o.viewFrom?hr(e):(o.viewFrom+=r,o.viewTo+=r);else if(t<=o.viewFrom&&n>=o.viewTo)hr(e);else if(t<=o.viewFrom){var i=vr(e,n,n+r,1);i?(o.view=o.view.slice(i.index),o.viewFrom=i.lineN,o.viewTo+=r):hr(e)}else if(n>=o.viewTo){var a=vr(e,t,t,-1);a?(o.view=o.view.slice(0,a.index),o.viewTo=a.lineN):hr(e)}else{var s=vr(e,t,t,-1),u=vr(e,n,n+r,1);s&&u?(o.view=o.view.slice(0,s.index).concat(an(e,s.lineN,u.lineN)).concat(o.view.slice(u.index)),o.viewTo+=r):hr(e)}var l=o.externalMeasured;l&&(n=o.lineN&&t=r.viewTo)){var i=r.view[fr(e,t)];if(null!=i.node){var a=i.changes||(i.changes=[]);-1==H(a,n)&&a.push(n)}}}function hr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function vr(e,t,n,r){var o,i=fr(e,t),a=e.display.view;if(!kt||n==e.doc.first+e.doc.size)return{index:i,lineN:n};for(var s=e.display.viewFrom,u=0;u0){if(i==a.length-1)return null;o=s+a[i].size-t,i++}else o=s-t;t+=o,n+=o}for(;Bt(e.doc,n)!=n;){if(i==(r<0?0:a.length-1))return null;n+=r*a[i-(r<0?1:0)].size,i+=r}return{index:i,lineN:n}}function gr(e){for(var t=e.display.view,n=0,r=0;r=e.display.viewTo||u.to().line0?a:e.defaultCharWidth())+"px"}if(r.other){var s=n.appendChild(M("div","\xa0","CodeMirror-cursor CodeMirror-secondarycursor"));s.style.display="",s.style.left=r.other.left+"px",s.style.top=r.other.top+"px",s.style.height=.85*(r.other.bottom-r.other.top)+"px"}}function wr(e,t){return e.top-t.top||e.left-t.left}function _r(e,t,n){var r=e.display,o=e.doc,i=document.createDocumentFragment(),a=En(e.display),s=a.left,u=Math.max(r.sizerWidth,Tn(e)-r.sizer.offsetLeft)-a.right,l="ltr"==o.direction;function c(e,t,n,r){t<0&&(t=0),t=Math.round(t),r=Math.round(r),i.appendChild(M("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?u-e:n)+"px;\n height: "+(r-t)+"px"))}function f(t,n,r){var i,a,f=Ge(o,t),d=f.text.length;function p(n,r){return Gn(e,tt(t,n),"div",f,r)}function h(t,n,r){var o=Jn(e,f,null,t),i="ltr"==n==("after"==r)?"left":"right";return p("after"==r?o.begin:o.end-(/\s/.test(f.text.charAt(o.end-1))?2:1),i)[i]}var v=ce(f,o.direction);return function(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var o=!1,i=0;it||t==n&&a.to==t)&&(r(Math.max(a.from,t),Math.min(a.to,n),1==a.level?"rtl":"ltr",i),o=!0)}o||r(t,n,"ltr")}(v,n||0,null==r?d:r,(function(e,t,o,f){var g="ltr"==o,m=p(e,g?"left":"right"),y=p(t-1,g?"right":"left"),b=null==n&&0==e,w=null==r&&t==d,_=0==f,x=!v||f==v.length-1;if(y.top-m.top<=3){var k=(l?w:b)&&x,C=(l?b:w)&&_?s:(g?m:y).left,O=k?u:(g?y:m).right;c(C,m.top,O-C,m.bottom)}else{var E,S,T,j;g?(E=l&&b&&_?s:m.left,S=l?u:h(e,o,"before"),T=l?s:h(t,o,"after"),j=l&&w&&x?u:y.right):(E=l?h(e,o,"before"):s,S=!l&&b&&_?u:m.right,T=!l&&w&&x?s:y.left,j=l?h(t,o,"after"):u),c(E,m.top,S-E,m.bottom),m.bottom0?t.blinker=setInterval((function(){e.hasFocus()||Er(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"}),e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function kr(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||Or(e))}function Cr(e){e.state.delayingBlurEvent=!0,setTimeout((function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&Er(e))}),100)}function Or(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ve(e,"focus",e,t),e.state.focused=!0,R(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),u&&setTimeout((function(){return e.display.input.reset(!0)}),20)),e.display.input.receivedFocus()),xr(e))}function Er(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ve(e,"blur",e,t),e.state.focused=!1,S(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout((function(){e.state.focused||(e.display.shift=!1)}),150))}function Sr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=Math.max(0,t.scroller.getBoundingClientRect().top),o=t.lineDiv.getBoundingClientRect().top,i=0,u=0;u.005||v<-.005)&&(oe.display.sizerWidth){var m=Math.ceil(d/ir(e.display));m>e.display.maxLineLength&&(e.display.maxLineLength=m,e.display.maxLine=l.line,e.display.maxLineChanged=!0)}}}Math.abs(i)>2&&(t.scroller.scrollTop+=i)}function Tr(e){if(e.widgets)for(var t=0;t=a&&(i=Qe(t,Vt(Ge(t,u))-e.wrapper.clientHeight),a=u)}return{from:i,to:Math.max(a,i+1)}}function Mr(e,t){var n=e.display,r=or(e.display);t.top<0&&(t.top=0);var o=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,i=jn(e),a={};t.bottom-t.top>i&&(t.bottom=t.top+i);var s=e.doc.height+On(n),u=t.tops-r;if(t.topo+i){var c=Math.min(t.top,(l?s:t.bottom)-i);c!=o&&(a.scrollTop=c)}var f=e.options.fixedGutter?0:n.gutters.offsetWidth,d=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-f,p=Tn(e)-n.gutters.offsetWidth,h=t.right-t.left>p;return h&&(t.right=t.left+p),t.left<10?a.scrollLeft=0:t.leftp+d-3&&(a.scrollLeft=t.right+(h?0:10)-p),a}function Lr(e,t){null!=t&&(Rr(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Ar(e){Rr(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Pr(e,t,n){null==t&&null==n||Rr(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function Rr(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Dr(e,Kn(e,t.from),Kn(e,t.to),t.margin))}function Dr(e,t,n,r){var o=Mr(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});Pr(e,o.scrollLeft,o.scrollTop)}function Ir(e,t){Math.abs(e.doc.scrollTop-t)<2||(n||lo(e,{top:t}),Nr(e,t,!0),n&&lo(e),oo(e,100))}function Nr(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),(e.display.scroller.scrollTop!=t||n)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function zr(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,po(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Fr(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+On(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Sn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}var Br=function(e,t,n){this.cm=n;var r=this.vert=M("div",[M("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),o=this.horiz=M("div",[M("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=o.tabIndex=-1,e(r),e(o),de(r,"scroll",(function(){r.clientHeight&&t(r.scrollTop,"vertical")})),de(o,"scroll",(function(){o.clientWidth&&t(o.scrollLeft,"horizontal")})),this.checkedZeroWidth=!1,a&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};Br.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,n=e.scrollHeight>e.clientHeight+1,r=e.nativeBarWidth;if(n){this.vert.style.display="block",this.vert.style.bottom=t?r+"px":"0";var o=e.viewHeight-(t?r:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+o)+"px"}else this.vert.scrollTop=0,this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=n?r+"px":"0",this.horiz.style.left=e.barLeft+"px";var i=e.viewWidth-e.barLeft-(n?r:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+i)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==r&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:n?r:0,bottom:t?r:0}},Br.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},Br.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},Br.prototype.zeroWidthHack=function(){var e=b&&!h?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new B,this.disableVert=new B},Br.prototype.enableZeroWidthBar=function(e,t,n){e.style.pointerEvents="auto",t.set(1e3,(function r(){var o=e.getBoundingClientRect();("vert"==n?document.elementFromPoint(o.right-1,(o.top+o.bottom)/2):document.elementFromPoint((o.right+o.left)/2,o.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,r)}))},Br.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var Hr=function(){};function Ur(e,t){t||(t=Fr(e));var n=e.display.barWidth,r=e.display.barHeight;Wr(e,t);for(var o=0;o<4&&n!=e.display.barWidth||r!=e.display.barHeight;o++)n!=e.display.barWidth&&e.options.lineWrapping&&Sr(e),Wr(e,Fr(e)),n=e.display.barWidth,r=e.display.barHeight}function Wr(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}Hr.prototype.update=function(){return{bottom:0,right:0}},Hr.prototype.setScrollLeft=function(){},Hr.prototype.setScrollTop=function(){},Hr.prototype.clear=function(){};var Vr={native:Br,null:Hr};function qr(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&S(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Vr[e.options.scrollbarStyle]((function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),de(t,"mousedown",(function(){e.state.focused&&setTimeout((function(){return e.display.input.focus()}),0)})),t.setAttribute("cm-not-content","true")}),(function(t,n){"horizontal"==n?zr(e,t):Ir(e,t)}),e),e.display.scrollbars.addClass&&R(e.display.wrapper,e.display.scrollbars.addClass)}var Yr=0;function Gr(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Yr,markArrays:null},t=e.curOp,sn?sn.ops.push(t):t.ownsGroup=sn={ops:[t],delayedCallbacks:[]}}function $r(e){var t=e.curOp;t&&function(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ao(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Zr(e){e.updatedDisplay=e.mustUpdate&&so(e.cm,e.update)}function Xr(e){var t=e.cm,n=t.display;e.updatedDisplay&&Sr(t),e.barMeasure=Fr(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Ln(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Sn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Tn(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}function Qr(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft(window.innerHeight||document.documentElement.clientHeight)&&(o=!1),null!=o&&!v){var i=M("div","\u200b",null,"position: absolute;\n top: "+(t.top-n.viewOffset-Cn(e.display))+"px;\n height: "+(t.bottom-t.top+Sn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(i),i.scrollIntoView(o),e.display.lineSpace.removeChild(i)}}}(t,function(e,t,n,r){var o;null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==t.sticky?tt(t.line,t.ch+1,"before"):t,t=t.ch?tt(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t);for(var i=0;i<5;i++){var a=!1,s=$n(e,t),u=n&&n!=t?$n(e,n):s,l=Mr(e,o={left:Math.min(s.left,u.left),top:Math.min(s.top,u.top)-r,right:Math.max(s.left,u.left),bottom:Math.max(s.bottom,u.bottom)+r}),c=e.doc.scrollTop,f=e.doc.scrollLeft;if(null!=l.scrollTop&&(Ir(e,l.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(a=!0)),null!=l.scrollLeft&&(zr(e,l.scrollLeft),Math.abs(e.doc.scrollLeft-f)>1&&(a=!0)),!a)break}return o}(t,ut(r,e.scrollToPos.from),ut(r,e.scrollToPos.to),e.scrollToPos.margin));var o=e.maybeHiddenMarkers,i=e.maybeUnhiddenMarkers;if(o)for(var a=0;a=e.display.viewTo)){var n=+new Date+e.options.workTime,r=ht(e,t.highlightFrontier),o=[];t.iter(r.line,Math.min(t.first+t.size,e.display.viewTo+500),(function(i){if(r.line>=e.display.viewFrom){var a=i.styles,s=i.text.length>e.options.maxHighlightLength?We(t.mode,r.state):null,u=dt(e,i,r,!0);s&&(r.state=s),i.styles=u.styles;var l=i.styleClasses,c=u.classes;c?i.styleClasses=c:l&&(i.styleClasses=null);for(var f=!a||a.length!=i.styles.length||l!=c&&(!l||!c||l.bgClass!=c.bgClass||l.textClass!=c.textClass),d=0;!f&&dn)return oo(e,e.options.workDelay),!0})),t.highlightFrontier=r.line,t.modeFrontier=Math.max(t.modeFrontier,r.line),o.length&&eo(e,(function(){for(var t=0;t=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==gr(e))return!1;ho(e)&&(hr(e),t.dims=ar(e));var o=r.first+r.size,i=Math.max(t.visible.from-e.options.viewportMargin,r.first),a=Math.min(o,t.visible.to+e.options.viewportMargin);n.viewFroma&&n.viewTo-a<20&&(a=Math.min(o,n.viewTo)),kt&&(i=Bt(e.doc,i),a=Ht(e.doc,a));var s=i!=n.viewFrom||a!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;!function(e,t,n){var r=e.display;0==r.view.length||t>=r.viewTo||n<=r.viewFrom?(r.view=an(e,t,n),r.viewFrom=t):(r.viewFrom>t?r.view=an(e,t,r.viewFrom).concat(r.view):r.viewFromn&&(r.view=r.view.slice(0,fr(e,n)))),r.viewTo=n}(e,i,a),n.viewOffset=Vt(Ge(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var l=gr(e);if(!s&&0==l&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var c=function(e){if(e.hasFocus())return null;var t=P();if(!t||!A(e.display.lineDiv,t))return null;var n={activeElt:t};if(window.getSelection){var r=window.getSelection();r.anchorNode&&r.extend&&A(e.display.lineDiv,r.anchorNode)&&(n.anchorNode=r.anchorNode,n.anchorOffset=r.anchorOffset,n.focusNode=r.focusNode,n.focusOffset=r.focusOffset)}return n}(e);return l>4&&(n.lineDiv.style.display="none"),function(e,t,n){var r=e.display,o=e.options.lineNumbers,i=r.lineDiv,a=i.firstChild;function s(t){var n=t.nextSibling;return u&&b&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),n}for(var l=r.view,c=r.viewFrom,f=0;f-1&&(p=!1),fn(e,d,c,n)),p&&(T(d.lineNumber),d.lineNumber.appendChild(document.createTextNode(et(e.options,c)))),a=d.node.nextSibling}else{var h=yn(e,d,c,n);i.insertBefore(h,a)}c+=d.size}for(;a;)a=s(a)}(e,n.updateLineNumbers,t.dims),l>4&&(n.lineDiv.style.display=""),n.renderedView=n.view,function(e){if(e&&e.activeElt&&e.activeElt!=P()&&(e.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(e.activeElt.nodeName)&&e.anchorNode&&A(document.body,e.anchorNode)&&A(document.body,e.focusNode))){var t=window.getSelection(),n=document.createRange();n.setEnd(e.anchorNode,e.anchorOffset),n.collapse(!1),t.removeAllRanges(),t.addRange(n),t.extend(e.focusNode,e.focusOffset)}}(c),T(n.cursorDiv),T(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,s&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,oo(e,400)),n.updateLineNumbers=null,!0}function uo(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Tn(e))r&&(t.visible=jr(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+On(e.display)-jn(e),n.top)}),t.visible=jr(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!so(e,t))break;Sr(e);var o=Fr(e);mr(e),Ur(e,o),fo(e,o),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function lo(e,t){var n=new ao(e,t);if(so(e,n)){Sr(e),uo(e,n);var r=Fr(e);mr(e),Ur(e,r),fo(e,r),n.finish()}}function co(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px",ln(e,"gutterChanged",e)}function fo(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Sn(e)+"px"}function po(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=sr(t)-t.scroller.scrollLeft+e.doc.scrollLeft,o=t.gutters.offsetWidth,i=r+"px",a=0;a=102&&(null==e.display.chromeScrollHack?e.display.sizer.style.pointerEvents="none":clearTimeout(e.display.chromeScrollHack),e.display.chromeScrollHack=setTimeout((function(){e.display.chromeScrollHack=null,e.display.sizer.style.pointerEvents=""}),100));var r=_o(t),o=r.x,i=r.y,a=wo;0===t.deltaMode&&(o=t.deltaX,i=t.deltaY,a=1);var s=e.display,l=s.scroller,p=l.scrollWidth>l.clientWidth,h=l.scrollHeight>l.clientHeight;if(o&&p||i&&h){if(i&&b&&u)e:for(var v=t.target,g=s.view;v!=l;v=v.parentNode)for(var m=0;m=0&&nt(e,r.to())<=0)return n}return-1};var Oo=function(e,t){this.anchor=e,this.head=t};function Eo(e,t,n){var r=e&&e.options.selectionsMayTouch,o=t[n];t.sort((function(e,t){return nt(e.from(),t.from())})),n=H(t,o);for(var i=1;i0:u>=0){var l=at(s.from(),a.from()),c=it(s.to(),a.to()),f=s.empty()?a.from()==a.head:s.from()==s.head;i<=n&&--n,t.splice(--i,2,new Oo(f?c:l,f?l:c))}}return new Co(t,n)}function So(e,t){return new Co([new Oo(e,t||e)],0)}function To(e){return e.text?tt(e.from.line+e.text.length-1,K(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function jo(e,t){if(nt(e,t.from)<0)return e;if(nt(e,t.to)<=0)return To(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=To(t).ch-t.to.ch),tt(n,r)}function Mo(e,t){for(var n=[],r=0;r1&&e.remove(s.line+1,h-1),e.insert(s.line+1,m)}ln(e,"change",e,t)}function Io(e,t,n){!function e(r,o,i){if(r.linked)for(var a=0;as-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(i=function(e,t){return t?(Ho(e.done),K(e.done)):e.done.length&&!K(e.done).ranges?K(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),K(e.done)):void 0}(o,o.lastOp==r)))a=K(i.changes),0==nt(t.from,t.to)&&0==nt(t.from,a.to)?a.to=To(t):i.changes.push(Bo(e,t));else{var u=K(o.done);for(u&&u.ranges||Vo(e.sel,o.done),i={changes:[Bo(e,t)],generation:o.generation},o.done.push(i);o.done.length>o.undoDepth;)o.done.shift(),o.done[0].ranges||o.done.shift()}o.done.push(n),o.generation=++o.maxGeneration,o.lastModTime=o.lastSelTime=s,o.lastOp=o.lastSelOp=r,o.lastOrigin=o.lastSelOrigin=t.origin,a||ve(e,"historyAdded")}function Wo(e,t,n,r){var o=e.history,i=r&&r.origin;n==o.lastSelOp||i&&o.lastSelOrigin==i&&(o.lastModTime==o.lastSelTime&&o.lastOrigin==i||function(e,t,n,r){var o=t.charAt(0);return"*"==o||"+"==o&&n.ranges.length==r.ranges.length&&n.somethingSelected()==r.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,i,K(o.done),t))?o.done[o.done.length-1]=t:Vo(t,o.done),o.lastSelTime=+new Date,o.lastSelOrigin=i,o.lastSelOp=n,r&&!1!==r.clearRedo&&Ho(o.undone)}function Vo(e,t){var n=K(t);n&&n.ranges&&n.equals(e)||t.push(e)}function qo(e,t,n,r){var o=t["spans_"+e.id],i=0;e.iter(Math.max(e.first,n),Math.min(e.first+e.size,r),(function(n){n.markedSpans&&((o||(o=t["spans_"+e.id]={}))[i]=n.markedSpans),++i}))}function Yo(e){if(!e)return null;for(var t,n=0;n-1&&(K(s)[f]=l[f],delete l[f])}}}return r}function Ko(e,t,n,r){if(r){var o=e.anchor;if(n){var i=nt(t,o)<0;i!=nt(n,o)<0?(o=t,t=n):i!=nt(t,n)<0&&(t=n)}return new Oo(o,t)}return new Oo(n||t,t)}function Zo(e,t,n,r,o){null==o&&(o=e.cm&&(e.cm.display.shift||e.extend)),ti(e,new Co([Ko(e.sel.primary(),t,n,o)],0),r)}function Xo(e,t,n){for(var r=[],o=e.cm&&(e.cm.display.shift||e.extend),i=0;i=t.ch:s.to>t.ch))){if(o&&(ve(u,"beforeCursorEnter"),u.explicitlyCleared)){if(i.markedSpans){--a;continue}break}if(!u.atomic)continue;if(n){var f=u.find(r<0?1:-1),d=void 0;if((r<0?c:l)&&(f=ui(e,f,-r,f&&f.line==t.line?i:null)),f&&f.line==t.line&&(d=nt(f,n))&&(r<0?d<0:d>0))return ai(e,f,t,r,o)}var p=u.find(r<0?-1:1);return(r<0?l:c)&&(p=ui(e,p,r,p.line==t.line?i:null)),p?ai(e,p,t,r,o):null}}return t}function si(e,t,n,r,o){var i=r||1,a=ai(e,t,n,i,o)||!o&&ai(e,t,n,i,!0)||ai(e,t,n,-i,o)||!o&&ai(e,t,n,-i,!0);return a||(e.cantEdit=!0,tt(e.first,0))}function ui(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ut(e,tt(t.line-1)):null:n>0&&t.ch==(r||Ge(e,t.line)).text.length?t.line0)){var c=[u,1],f=nt(l.from,s.from),d=nt(l.to,s.to);(f<0||!a.inclusiveLeft&&!f)&&c.push({from:l.from,to:s.from}),(d>0||!a.inclusiveRight&&!d)&&c.push({from:s.to,to:l.to}),o.splice.apply(o,c),u+=c.length-3}}return o}(e,t.from,t.to);if(r)for(var o=r.length-1;o>=0;--o)di(e,{from:r[o].from,to:r[o].to,text:o?[""]:t.text,origin:t.origin});else di(e,t)}}function di(e,t){if(1!=t.text.length||""!=t.text[0]||0!=nt(t.from,t.to)){var n=Mo(e,t);Uo(e,t,n,e.cm?e.cm.curOp.id:NaN),vi(e,t,n,St(e,t));var r=[];Io(e,(function(e,n){n||-1!=H(r,e.history)||(bi(e.history,t),r.push(e.history)),vi(e,t,null,St(e,t))}))}}function pi(e,t,n){var r=e.cm&&e.cm.state.suppressEdits;if(!r||n){for(var o,i=e.history,a=e.sel,s="undo"==t?i.done:i.undone,u="undo"==t?i.undone:i.done,l=0;l=0;--p){var h=d(p);if(h)return h.v}}}}function hi(e,t){if(0!=t&&(e.first+=t,e.sel=new Co(Z(e.sel.ranges,(function(e){return new Oo(tt(e.anchor.line+t,e.anchor.ch),tt(e.head.line+t,e.head.ch))})),e.sel.primIndex),e.cm)){dr(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;re.lastLine())){if(t.from.linei&&(t={from:t.from,to:tt(i,Ge(e,i).text.length),text:[t.text[0]],origin:t.origin}),t.removed=$e(e,t.from,t.to),n||(n=Mo(e,t)),e.cm?function(e,t,n){var r=e.doc,o=e.display,i=t.from,a=t.to,s=!1,u=i.line;e.options.lineWrapping||(u=Xe(Ft(Ge(r,i.line))),r.iter(u,a.line+1,(function(e){if(e==o.maxLine)return s=!0,!0}))),r.sel.contains(t.from,t.to)>-1&&me(e),Do(r,t,n,ur(e)),e.options.lineWrapping||(r.iter(u,i.line+t.text.length,(function(e){var t=qt(e);t>o.maxLineLength&&(o.maxLine=e,o.maxLineLength=t,o.maxLineChanged=!0,s=!1)})),s&&(e.curOp.updateMaxLine=!0)),function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontiern;r--){var o=Ge(e,r).stateAfter;if(o&&(!(o instanceof ct)||r+o.lookAhead1||!(this.children[0]instanceof _i))){var s=[];this.collapse(s),this.children=[new _i(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var a=o.lines.length%25+25,s=a;s10);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r0||0==a&&!1!==i.clearWhenEmpty)return i;if(i.replacedWith&&(i.collapsed=!0,i.widgetNode=L("span",[i.replacedWith],"CodeMirror-widget"),r.handleMouseEvents||i.widgetNode.setAttribute("cm-ignore-events","true"),r.insertLeft&&(i.widgetNode.insertLeft=!0)),i.collapsed){if(zt(e,t.line,t,n,i)||t.line!=n.line&&zt(e,n.line,t,n,i))throw new Error("Inserting collapsed marker partially overlapping an existing one");kt=!0}i.addToHistory&&Uo(e,{from:t,to:n,origin:"markText"},e.sel,NaN);var s,u=t.line,l=e.cm;if(e.iter(u,n.line+1,(function(r){l&&i.collapsed&&!l.options.lineWrapping&&Ft(r)==l.display.maxLine&&(s=!0),i.collapsed&&u!=t.line&&Ze(r,0),function(e,t,n){var r=n&&window.WeakSet&&(n.markedSpans||(n.markedSpans=new WeakSet));r&&e.markedSpans&&r.has(e.markedSpans)?e.markedSpans.push(t):(e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],r&&r.add(e.markedSpans)),t.marker.attachLine(e)}(r,new Ct(i,u==t.line?t.ch:null,u==n.line?n.ch:null),e.cm&&e.cm.curOp),++u})),i.collapsed&&e.iter(t.line,n.line+1,(function(t){Ut(e,t)&&Ze(t,0)})),i.clearOnEnter&&de(i,"beforeCursorEnter",(function(){return i.clear()})),i.readOnly&&(xt=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),i.collapsed&&(i.id=++Oi,i.atomic=!0),l){if(s&&(l.curOp.updateMaxLine=!0),i.collapsed)dr(l,t.line,n.line+1);else if(i.className||i.startStyle||i.endStyle||i.css||i.attributes||i.title)for(var c=t.line;c<=n.line;c++)pr(l,c,"text");i.atomic&&oi(l.doc),ln(l,"markerAdded",l,i)}return i}Ei.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Gr(e),ye(this,"clear")){var n=this.find();n&&ln(this,"clear",n.from,n.to)}for(var r=null,o=null,i=0;ie.display.maxLineLength&&(e.display.maxLine=l,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=r&&e&&this.collapsed&&dr(e,r,o+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&oi(e.doc)),e&&ln(e,"markerCleared",e,this,r,o),t&&$r(e),this.parent&&this.parent.clear()}},Ei.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var o=0;o=0;u--)fi(this,r[u]);s?ei(this,s):this.cm&&Ar(this.cm)})),undo:ro((function(){pi(this,"undo")})),redo:ro((function(){pi(this,"redo")})),undoSelection:ro((function(){pi(this,"undo",!0)})),redoSelection:ro((function(){pi(this,"redo",!0)})),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r=e.ch)&&t.push(o.marker.parent||o.marker)}return t},findMarks:function(e,t,n){e=ut(this,e),t=ut(this,t);var r=[],o=e.line;return this.iter(e.line,t.line+1,(function(i){var a=i.markedSpans;if(a)for(var s=0;s=u.to||null==u.from&&o!=e.line||null!=u.from&&o==t.line&&u.from>=t.ch||n&&!n(u.marker)||r.push(u.marker.parent||u.marker)}++o})),r},getAllMarks:function(){var e=[];return this.iter((function(t){var n=t.markedSpans;if(n)for(var r=0;re)return t=e,!0;e-=i,++n})),ut(this,tt(n,t))},indexFromPos:function(e){var t=(e=ut(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout((function(){return t.display.input.focus()}),20);try{var f=e.dataTransfer.getData("Text");if(f){var d;if(t.state.draggingText&&!t.state.draggingText.copy&&(d=t.listSelections()),ni(t.doc,So(n,n)),d)for(var p=0;p=0;t--)gi(e.doc,"",r[t].from,r[t].to,"+delete");Ar(e)}))}function Ji(e,t,n){var r=ie(e.text,t+n,n);return r<0||r>e.text.length?null:r}function ea(e,t,n){var r=Ji(e,t.ch,n);return null==r?null:new tt(t.line,r,n<0?"after":"before")}function ta(e,t,n,r,o){if(e){"rtl"==t.doc.direction&&(o=-o);var i=ce(n,t.doc.direction);if(i){var a,s=o<0?K(i):i[0],u=o<0==(1==s.level)?"after":"before";if(s.level>0||"rtl"==t.doc.direction){var l=Pn(t,n);a=o<0?n.text.length-1:0;var c=Rn(t,l,a).top;a=ae((function(e){return Rn(t,l,e).top==c}),o<0==(1==s.level)?s.from:s.to-1,a),"before"==u&&(a=Ji(n,a,1))}else a=o<0?s.to:s.from;return new tt(r,a,u)}}return new tt(r,o<0?n.text.length:0,o<0?"before":"after")}Vi.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Vi.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Vi.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Vi.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Vi.default=b?Vi.macDefault:Vi.pcDefault;var na={selectAll:li,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),W)},killLine:function(e){return Qi(e,(function(t){if(t.empty()){var n=Ge(e.doc,t.head.line).text.length;return t.head.ch==n&&t.head.line0)o=new tt(o.line,o.ch+1),e.replaceRange(i.charAt(o.ch-1)+i.charAt(o.ch-2),tt(o.line,o.ch-2),o,"+transpose");else if(o.line>e.doc.first){var a=Ge(e.doc,o.line-1).text;a&&(o=new tt(o.line,1),e.replaceRange(i.charAt(0)+e.doc.lineSeparator()+a.charAt(a.length-1),tt(o.line-1,a.length-1),o,"+transpose"))}n.push(new Oo(o,o))}e.setSelections(n)}))},newlineAndIndent:function(e){return eo(e,(function(){for(var t=e.listSelections(),n=t.length-1;n>=0;n--)e.replaceRange(e.doc.lineSeparator(),t[n].anchor,t[n].head,"+input");t=e.listSelections();for(var r=0;r-1&&(nt((o=l.ranges[o]).from(),t)<0||t.xRel>0)&&(nt(o.to(),t)>0||t.xRel<0)?function(e,t,n,r){var o=e.display,i=!1,l=to(e,(function(t){u&&(o.scroller.draggable=!1),e.state.draggingText=!1,e.state.delayingBlurEvent&&(e.hasFocus()?e.state.delayingBlurEvent=!1:Cr(e)),he(o.wrapper.ownerDocument,"mouseup",l),he(o.wrapper.ownerDocument,"mousemove",c),he(o.scroller,"dragstart",f),he(o.scroller,"drop",l),i||(we(t),r.addNew||Zo(e.doc,n,null,null,r.extend),u&&!p||a&&9==s?setTimeout((function(){o.wrapper.ownerDocument.body.focus({preventScroll:!0}),o.input.focus()}),20):o.input.focus())})),c=function(e){i=i||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},f=function(){return i=!0};u&&(o.scroller.draggable=!0),e.state.draggingText=l,l.copy=!r.moveOnDrag,de(o.wrapper.ownerDocument,"mouseup",l),de(o.wrapper.ownerDocument,"mousemove",c),de(o.scroller,"dragstart",f),de(o.scroller,"drop",l),e.state.delayingBlurEvent=!0,setTimeout((function(){return o.input.focus()}),20),o.scroller.dragDrop&&o.scroller.dragDrop()}(e,r,t,i):function(e,t,n,r){a&&Cr(e);var o=e.display,i=e.doc;we(t);var s,u,l=i.sel,c=l.ranges;if(r.addNew&&!r.extend?(u=i.sel.contains(n),s=u>-1?c[u]:new Oo(n,n)):(s=i.sel.primary(),u=i.sel.primIndex),"rectangle"==r.unit)r.addNew||(s=new Oo(n,n)),n=cr(e,t,!0,!0),u=-1;else{var f=ya(e,n,r.unit);s=r.extend?Ko(s,f.anchor,f.head,r.extend):f}r.addNew?-1==u?(u=c.length,ti(i,Eo(e,c.concat([s]),u),{scroll:!1,origin:"*mouse"})):c.length>1&&c[u].empty()&&"char"==r.unit&&!r.extend?(ti(i,Eo(e,c.slice(0,u).concat(c.slice(u+1)),0),{scroll:!1,origin:"*mouse"}),l=i.sel):Qo(i,u,s,V):(u=0,ti(i,new Co([s],0),V),l=i.sel);var d=n;function p(t){if(0!=nt(d,t))if(d=t,"rectangle"==r.unit){for(var o=[],a=e.options.tabSize,c=F(Ge(i,n.line).text,n.ch,a),f=F(Ge(i,t.line).text,t.ch,a),p=Math.min(c,f),h=Math.max(c,f),v=Math.min(n.line,t.line),g=Math.min(e.lastLine(),Math.max(n.line,t.line));v<=g;v++){var m=Ge(i,v).text,y=Y(m,p,a);p==h?o.push(new Oo(tt(v,y),tt(v,y))):m.length>y&&o.push(new Oo(tt(v,y),tt(v,Y(m,h,a))))}o.length||o.push(new Oo(n,n)),ti(i,Eo(e,l.ranges.slice(0,u).concat(o),u),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=s,_=ya(e,t,r.unit),x=w.anchor;nt(_.anchor,x)>0?(b=_.head,x=at(w.from(),_.anchor)):(b=_.anchor,x=it(w.to(),_.head));var k=l.ranges.slice(0);k[u]=function(e,t){var n=t.anchor,r=t.head,o=Ge(e.doc,n.line);if(0==nt(n,r)&&n.sticky==r.sticky)return t;var i=ce(o);if(!i)return t;var a=ue(i,n.ch,n.sticky),s=i[a];if(s.from!=n.ch&&s.to!=n.ch)return t;var u,l=a+(s.from==n.ch==(1!=s.level)?0:1);if(0==l||l==i.length)return t;if(r.line!=n.line)u=(r.line-n.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=ue(i,r.ch,r.sticky),f=c-a||(r.ch-n.ch)*(1==s.level?-1:1);u=c==l-1||c==l?f<0:f>0}var d=i[l+(u?-1:0)],p=u==(1==d.level),h=p?d.from:d.to,v=p?"after":"before";return n.ch==h&&n.sticky==v?t:new Oo(new tt(n.line,h,v),r)}(e,new Oo(ut(i,x),b)),ti(i,Eo(e,k,u),V)}}var h=o.wrapper.getBoundingClientRect(),v=0;function g(t){e.state.selectingText=!1,v=1/0,t&&(we(t),o.input.focus()),he(o.wrapper.ownerDocument,"mousemove",m),he(o.wrapper.ownerDocument,"mouseup",y),i.history.lastSelOrigin=null}var m=to(e,(function(t){0!==t.buttons&&Oe(t)?function t(n){var a=++v,s=cr(e,n,!0,"rectangle"==r.unit);if(s)if(0!=nt(s,d)){e.curOp.focus=P(),p(s);var u=jr(o,i);(s.line>=u.to||s.lineh.bottom?20:0;l&&setTimeout(to(e,(function(){v==a&&(o.scroller.scrollTop+=l,t(n))})),50)}}(t):g(t)})),y=to(e,g);e.state.selectingText=y,de(o.wrapper.ownerDocument,"mousemove",m),de(o.wrapper.ownerDocument,"mouseup",y)}(e,r,t,i)}(t,r,i,e):Ce(e)==n.scroller&&we(e):2==o?(r&&Zo(t.doc,r),setTimeout((function(){return n.input.focus()}),20)):3==o&&(C?t.display.input.onContextMenu(e):Cr(t)))}}function ya(e,t,n){if("char"==n)return new Oo(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new Oo(tt(t.line,0),ut(e.doc,tt(t.line+1,0)));var r=n(e,t);return new Oo(r.from,r.to)}function ba(e,t,n,r){var o,i;if(t.touches)o=t.touches[0].clientX,i=t.touches[0].clientY;else try{o=t.clientX,i=t.clientY}catch(e){return!1}if(o>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&we(t);var a=e.display,s=a.lineDiv.getBoundingClientRect();if(i>s.bottom||!ye(e,n))return xe(t);i-=s.top-a.viewOffset;for(var u=0;u=o)return ve(e,n,e,Qe(e.doc,i),e.display.gutterSpecs[u].className,t),xe(t)}}function wa(e,t){return ba(e,t,"gutterClick",!0)}function _a(e,t){kn(e.display,t)||function(e,t){return!!ye(e,"gutterContextMenu")&&ba(e,t,"gutterContextMenu",!1)}(e,t)||ge(e,t,"contextmenu")||C||e.display.input.onContextMenu(t)}function xa(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Hn(e)}ga.prototype.compare=function(e,t,n){return this.time+400>e&&0==nt(t,this.pos)&&n==this.button};var ka={toString:function(){return"CodeMirror.Init"}},Ca={},Oa={};function Ea(e,t,n){if(!t!=!(n&&n!=ka)){var r=e.display.dragFunctions,o=t?de:he;o(e.display.scroller,"dragstart",r.start),o(e.display.scroller,"dragenter",r.enter),o(e.display.scroller,"dragover",r.over),o(e.display.scroller,"dragleave",r.leave),o(e.display.scroller,"drop",r.drop)}}function Sa(e){e.options.lineWrapping?(R(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(S(e.display.wrapper,"CodeMirror-wrap"),Yt(e)),lr(e),dr(e),Hn(e),setTimeout((function(){return Ur(e)}),100)}function Ta(e,t){var n=this;if(!(this instanceof Ta))return new Ta(e,t);this.options=t=t?z(t):{},z(Ca,t,!1);var r=t.value;"string"==typeof r?r=new Ai(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var o=new Ta.inputStyles[t.inputStyle](this),i=this.display=new yo(e,r,o,t);for(var l in i.wrapper.CodeMirror=this,xa(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),qr(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new B,keySeq:null,specialChars:null},t.autofocus&&!y&&i.input.focus(),a&&s<11&&setTimeout((function(){return n.display.input.reset(!0)}),20),function(e){var t=e.display;de(t.scroller,"mousedown",to(e,ma)),de(t.scroller,"dblclick",a&&s<11?to(e,(function(t){if(!ge(e,t)){var n=cr(e,t);if(n&&!wa(e,t)&&!kn(e.display,t)){we(t);var r=e.findWordAt(n);Zo(e.doc,r.anchor,r.head)}}})):function(t){return ge(e,t)||we(t)}),de(t.scroller,"contextmenu",(function(t){return _a(e,t)})),de(t.input.getField(),"contextmenu",(function(n){t.scroller.contains(n.target)||_a(e,n)}));var n,r={end:0};function o(){t.activeTouch&&(n=setTimeout((function(){return t.activeTouch=null}),1e3),(r=t.activeTouch).end=+new Date)}function i(e,t){if(null==t.left)return!0;var n=t.left-e.left,r=t.top-e.top;return n*n+r*r>400}de(t.scroller,"touchstart",(function(o){if(!ge(e,o)&&!function(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}(o)&&!wa(e,o)){t.input.ensurePolled(),clearTimeout(n);var i=+new Date;t.activeTouch={start:i,moved:!1,prev:i-r.end<=300?r:null},1==o.touches.length&&(t.activeTouch.left=o.touches[0].pageX,t.activeTouch.top=o.touches[0].pageY)}})),de(t.scroller,"touchmove",(function(){t.activeTouch&&(t.activeTouch.moved=!0)})),de(t.scroller,"touchend",(function(n){var r=t.activeTouch;if(r&&!kn(t,n)&&null!=r.left&&!r.moved&&new Date-r.start<300){var a,s=e.coordsChar(t.activeTouch,"page");a=!r.prev||i(r,r.prev)?new Oo(s,s):!r.prev.prev||i(r,r.prev.prev)?e.findWordAt(s):new Oo(tt(s.line,0),ut(e.doc,tt(s.line+1,0))),e.setSelection(a.anchor,a.head),e.focus(),we(n)}o()})),de(t.scroller,"touchcancel",o),de(t.scroller,"scroll",(function(){t.scroller.clientHeight&&(Ir(e,t.scroller.scrollTop),zr(e,t.scroller.scrollLeft,!0),ve(e,"scroll",e))})),de(t.scroller,"mousewheel",(function(t){return ko(e,t)})),de(t.scroller,"DOMMouseScroll",(function(t){return ko(e,t)})),de(t.wrapper,"scroll",(function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0})),t.dragFunctions={enter:function(t){ge(e,t)||ke(t)},over:function(t){ge(e,t)||(function(e,t){var n=cr(e,t);if(n){var r=document.createDocumentFragment();br(e,n,r),e.display.dragCursor||(e.display.dragCursor=M("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),j(e.display.dragCursor,r)}}(e,t),ke(t))},start:function(t){return function(e,t){if(a&&(!e.state.draggingText||+new Date-Pi<100))ke(t);else if(!ge(e,t)&&!kn(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!p)){var n=M("img",null,null,"position: fixed; left: 0; top: 0;");n.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",d&&(n.width=n.height=1,e.display.wrapper.appendChild(n),n._top=n.offsetTop),t.dataTransfer.setDragImage(n,0,0),d&&n.parentNode.removeChild(n)}}(e,t)},drop:to(e,Ri),leave:function(t){ge(e,t)||Di(e)}};var u=t.input.getField();de(u,"keyup",(function(t){return da.call(e,t)})),de(u,"keydown",to(e,fa)),de(u,"keypress",to(e,pa)),de(u,"focus",(function(t){return Or(e,t)})),de(u,"blur",(function(t){return Er(e,t)}))}(this),zi(),Gr(this),this.curOp.forceUpdate=!0,No(this,r),t.autofocus&&!y||this.hasFocus()?setTimeout((function(){n.hasFocus()&&!n.state.focused&&Or(n)}),20):Er(this),Oa)Oa.hasOwnProperty(l)&&Oa[l](this,t[l],ka);ho(this),t.finishInit&&t.finishInit(this);for(var c=0;c150)){if(!r)return;n="prev"}}else l=0,n="not";"prev"==n?l=t>i.first?F(Ge(i,t-1).text,null,a):0:"add"==n?l=u+e.options.indentUnit:"subtract"==n?l=u-e.options.indentUnit:"number"==typeof n&&(l=u+n),l=Math.max(0,l);var f="",d=0;if(e.options.indentWithTabs)for(var p=Math.floor(l/a);p;--p)d+=a,f+="\t";if(da,u=Ae(t),l=null;if(s&&r.ranges.length>1)if(La&&La.text.join("\n")==t){if(r.ranges.length%La.text.length==0){l=[];for(var c=0;c=0;d--){var p=r.ranges[d],h=p.from(),v=p.to();p.empty()&&(n&&n>0?h=tt(h.line,h.ch-n):e.state.overwrite&&!s?v=tt(v.line,Math.min(Ge(i,v.line).text.length,v.ch+K(u).length)):s&&La&&La.lineWise&&La.text.join("\n")==u.join("\n")&&(h=v=tt(h.line,0)));var g={from:h,to:v,text:l?l[d%l.length]:u,origin:o||(s?"paste":e.state.cutIncoming>a?"cut":"+input")};fi(e.doc,g),ln(e,"inputRead",e,g)}t&&!s&&Da(e,t),Ar(e),e.curOp.updateInput<2&&(e.curOp.updateInput=f),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Ra(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");if(n)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||!t.hasFocus()||eo(t,(function(){return Pa(t,n,0,null,"paste")})),!0}function Da(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;r>=0;r--){var o=n.ranges[r];if(!(o.head.ch>100||r&&n.ranges[r-1].head.line==o.head.line)){var i=e.getModeAt(o.head),a=!1;if(i.electricChars){for(var s=0;s-1){a=Ma(e,o.head.line,"smart");break}}else i.electricInput&&i.electricInput.test(Ge(e.doc,o.head.line).text.slice(0,o.head.ch))&&(a=Ma(e,o.head.line,"smart"));a&&ln(e,"electricInput",e,o.head.line)}}}function Ia(e){for(var t=[],n=[],r=0;r0?0:-1));if(isNaN(c))a=null;else{var f=n>0?c>=55296&&c<56320:c>=56320&&c<57343;a=new tt(t.line,Math.max(0,Math.min(s.text.length,t.ch+n*(f?2:1))),-n)}}else a=o?function(e,t,n,r){var o=ce(t,e.doc.direction);if(!o)return ea(t,n,r);n.ch>=t.text.length?(n.ch=t.text.length,n.sticky="before"):n.ch<=0&&(n.ch=0,n.sticky="after");var i=ue(o,n.ch,n.sticky),a=o[i];if("ltr"==e.doc.direction&&a.level%2==0&&(r>0?a.to>n.ch:a.from=a.from&&d>=c.begin)){var p=f?"before":"after";return new tt(n.line,d,p)}}var h=function(e,t,r){for(var i=function(e,t){return t?new tt(n.line,u(e,1),"before"):new tt(n.line,e,"after")};e>=0&&e0==(1!=a.level),l=s?r.begin:u(r.end,-1);if(a.from<=l&&l0?c.end:u(c.begin,-1);return null==g||r>0&&g==t.text.length||!(v=h(r>0?0:o.length-1,r,l(g)))?null:v}(e.cm,s,t,n):ea(s,t,n);if(null==a){if(i||(l=t.line+u)=e.first+e.size||(t=new tt(l,t.ch,t.sticky),!(s=Ge(e,l))))return!1;t=ta(o,e.cm,s,t.line,u)}else t=a;return!0}if("char"==r||"codepoint"==r)l();else if("column"==r)l(!0);else if("word"==r||"group"==r)for(var c=null,f="group"==r,d=e.cm&&e.cm.getHelper(t,"wordChars"),p=!0;!(n<0)||l(!p);p=!1){var h=s.text.charAt(t.ch)||"\n",v=te(h,d)?"w":f&&"\n"==h?"n":!f||/\s/.test(h)?null:"p";if(!f||p||v||(v="s"),c&&c!=v){n<0&&(n=1,l(),t.sticky="after");break}if(v&&(c=v),n>0&&!l(!p))break}var g=si(e,t,i,a,!0);return rt(i,g)&&(g.hitSide=!0),g}function Ba(e,t,n,r){var o,i,a=e.doc,s=t.left;if("page"==r){var u=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),l=Math.max(u-.5*or(e.display),3);o=(n>0?t.bottom:t.top)+n*l}else"line"==r&&(o=n>0?t.bottom+3:t.top-3);for(;(i=Xn(e,s,o)).outside;){if(n<0?o<=0:o>=a.height){i.hitSide=!0;break}o+=5*n}return i}var Ha=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new B,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Ua(e,t){var n=An(e,t.line);if(!n||n.hidden)return null;var r=Ge(e.doc,t.line),o=Mn(n,r,t.line),i=ce(r,e.doc.direction),a="left";i&&(a=ue(i,t.ch)%2?"right":"left");var s=Nn(o.map,t.ch,a);return s.offset="right"==s.collapse?s.end:s.start,s}function Wa(e,t){return t&&(e.bad=!0),e}function Va(e,t,n){var r;if(t==e.display.lineDiv){if(!(r=e.display.lineDiv.childNodes[n]))return Wa(e.clipPos(tt(e.display.viewTo-1)),!0);t=null,n=0}else for(r=t;;r=r.parentNode){if(!r||r==e.display.lineDiv)return null;if(r.parentNode&&r.parentNode==e.display.lineDiv)break}for(var o=0;o=t.display.viewTo||i.line=t.display.viewFrom&&Ua(t,o)||{node:u[0].measure.map[2],offset:0},c=i.liner.firstLine()&&(a=tt(a.line-1,Ge(r.doc,a.line-1).length)),s.ch==Ge(r.doc,s.line).text.length&&s.lineo.viewTo-1)return!1;a.line==o.viewFrom||0==(e=fr(r,a.line))?(t=Xe(o.view[0].line),n=o.view[0].node):(t=Xe(o.view[e].line),n=o.view[e-1].node.nextSibling);var u,l,c=fr(r,s.line);if(c==o.view.length-1?(u=o.viewTo-1,l=o.lineDiv.lastChild):(u=Xe(o.view[c+1].line)-1,l=o.view[c+1].node.previousSibling),!n)return!1;for(var f=r.doc.splitLines(function(e,t,n,r,o){var i="",a=!1,s=e.doc.lineSeparator(),u=!1;function l(){a&&(i+=s,u&&(i+=s),a=u=!1)}function c(e){e&&(l(),i+=e)}function f(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void c(n);var i,d=t.getAttribute("cm-marker");if(d){var p=e.findMarks(tt(r,0),tt(o+1,0),(g=+d,function(e){return e.id==g}));return void(p.length&&(i=p[0].find(0))&&c($e(e.doc,i.from,i.to).join(s)))}if("false"==t.getAttribute("contenteditable"))return;var h=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;h&&l();for(var v=0;v1&&d.length>1;)if(K(f)==K(d))f.pop(),d.pop(),u--;else{if(f[0]!=d[0])break;f.shift(),d.shift(),t++}for(var p=0,h=0,v=f[0],g=d[0],m=Math.min(v.length,g.length);pa.ch&&y.charCodeAt(y.length-h-1)==b.charCodeAt(b.length-h-1);)p--,h++;f[f.length-1]=y.slice(0,y.length-h).replace(/^\u200b+/,""),f[0]=f[0].slice(p).replace(/\u200b+$/,"");var _=tt(t,p),x=tt(u,d.length?K(d).length-h:0);return f.length>1||f[0]||nt(_,x)?(gi(r.doc,f,_,x,"+input"),!0):void 0},Ha.prototype.ensurePolled=function(){this.forceCompositionEnd()},Ha.prototype.reset=function(){this.forceCompositionEnd()},Ha.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Ha.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout((function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()}),80))},Ha.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||eo(this.cm,(function(){return dr(e.cm)}))},Ha.prototype.setUneditable=function(e){e.contentEditable="false"},Ha.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||to(this.cm,Pa)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Ha.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Ha.prototype.onContextMenu=function(){},Ha.prototype.resetPosition=function(){},Ha.prototype.needsContentAttribute=!0;var Ya=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new B,this.hasSelection=!1,this.composing=null};Ya.prototype.init=function(e){var t=this,n=this,r=this.cm;this.createField(e);var o=this.textarea;function i(e){if(!ge(r,e)){if(r.somethingSelected())Aa({lineWise:!1,text:r.getSelections()});else{if(!r.options.lineWiseCopyCut)return;var t=Ia(r);Aa({lineWise:!0,text:t.text}),"cut"==e.type?r.setSelections(t.ranges,null,W):(n.prevInput="",o.value=t.text.join("\n"),I(o))}"cut"==e.type&&(r.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(o.style.width="0px"),de(o,"input",(function(){a&&s>=9&&t.hasSelection&&(t.hasSelection=null),n.poll()})),de(o,"paste",(function(e){ge(r,e)||Ra(e,r)||(r.state.pasteIncoming=+new Date,n.fastPoll())})),de(o,"cut",i),de(o,"copy",i),de(e.scroller,"paste",(function(t){if(!kn(e,t)&&!ge(r,t)){if(!o.dispatchEvent)return r.state.pasteIncoming=+new Date,void n.focus();var i=new Event("paste");i.clipboardData=t.clipboardData,o.dispatchEvent(i)}})),de(e.lineSpace,"selectstart",(function(t){kn(e,t)||we(t)})),de(o,"compositionstart",(function(){var e=r.getCursor("from");n.composing&&n.composing.range.clear(),n.composing={start:e,range:r.markText(e,r.getCursor("to"),{className:"CodeMirror-composing"})}})),de(o,"compositionend",(function(){n.composing&&(n.poll(),n.composing.range.clear(),n.composing=null)}))},Ya.prototype.createField=function(e){this.wrapper=za(),this.textarea=this.wrapper.firstChild},Ya.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},Ya.prototype.prepareSelection=function(){var e=this.cm,t=e.display,n=e.doc,r=yr(e);if(e.options.moveInputWithCursor){var o=$n(e,n.sel.primary().head,"div"),i=t.wrapper.getBoundingClientRect(),a=t.lineDiv.getBoundingClientRect();r.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,o.top+a.top-i.top)),r.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,o.left+a.left-i.left))}return r},Ya.prototype.showSelection=function(e){var t=this.cm.display;j(t.cursorDiv,e.cursors),j(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Ya.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var n=t.getSelection();this.textarea.value=n,t.state.focused&&I(this.textarea),a&&s>=9&&(this.hasSelection=n)}else e||(this.prevInput=this.textarea.value="",a&&s>=9&&(this.hasSelection=null))}},Ya.prototype.getField=function(){return this.textarea},Ya.prototype.supportsTouch=function(){return!1},Ya.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!y||P()!=this.textarea))try{this.textarea.focus()}catch(e){}},Ya.prototype.blur=function(){this.textarea.blur()},Ya.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Ya.prototype.receivedFocus=function(){this.slowPoll()},Ya.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,(function(){e.poll(),e.cm.state.focused&&e.slowPoll()}))},Ya.prototype.fastPoll=function(){var e=!1,t=this;t.pollingFast=!0,t.polling.set(20,(function n(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,n))}))},Ya.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||Pe(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var o=n.value;if(o==r&&!t.somethingSelected())return!1;if(a&&s>=9&&this.hasSelection===o||b&&/[\uf700-\uf7ff]/.test(o))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var i=o.charCodeAt(0);if(8203!=i||r||(r="\u200b"),8666==i)return this.reset(),this.cm.execCommand("undo")}for(var u=0,l=Math.min(r.length,o.length);u1e3||o.indexOf("\n")>-1?n.value=e.prevInput="":e.prevInput=o,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))})),!0},Ya.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Ya.prototype.onKeyPress=function(){a&&s>=9&&(this.hasSelection=null),this.fastPoll()},Ya.prototype.onContextMenu=function(e){var t=this,n=t.cm,r=n.display,o=t.textarea;t.contextMenuPending&&t.contextMenuPending();var i=cr(n,e),l=r.scroller.scrollTop;if(i&&!d){n.options.resetSelectionOnContextMenu&&-1==n.doc.sel.contains(i)&&to(n,ti)(n.doc,So(i),W);var c,f=o.style.cssText,p=t.wrapper.style.cssText,h=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",o.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-h.top-5)+"px; left: "+(e.clientX-h.left-5)+"px;\n z-index: 1000; background: "+(a?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",u&&(c=window.scrollY),r.input.focus(),u&&window.scrollTo(null,c),r.input.reset(),n.somethingSelected()||(o.value=t.prevInput=" "),t.contextMenuPending=m,r.selForContextMenu=n.doc.sel,clearTimeout(r.detectingSelectAll),a&&s>=9&&g(),C){ke(e);var v=function(){he(window,"mouseup",v),setTimeout(m,20)};de(window,"mouseup",v)}else setTimeout(m,50)}function g(){if(null!=o.selectionStart){var e=n.somethingSelected(),i="\u200b"+(e?o.value:"");o.value="\u21da",o.value=i,t.prevInput=e?"":"\u200b",o.selectionStart=1,o.selectionEnd=i.length,r.selForContextMenu=n.doc.sel}}function m(){if(t.contextMenuPending==m&&(t.contextMenuPending=!1,t.wrapper.style.cssText=p,o.style.cssText=f,a&&s<9&&r.scrollbars.setScrollTop(r.scroller.scrollTop=l),null!=o.selectionStart)){(!a||a&&s<9)&&g();var e=0,i=function(){r.selForContextMenu==n.doc.sel&&0==o.selectionStart&&o.selectionEnd>0&&"\u200b"==t.prevInput?to(n,li)(n):e++<10?r.detectingSelectAll=setTimeout(i,500):(r.selForContextMenu=null,r.input.reset())};r.detectingSelectAll=setTimeout(i,200)}}},Ya.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},Ya.prototype.setUneditable=function(){},Ya.prototype.needsContentAttribute=!1,function(e){var t=e.optionHandlers;function n(n,r,o,i){e.defaults[n]=r,o&&(t[n]=i?function(e,t,n){n!=ka&&o(e,t,n)}:o)}e.defineOption=n,e.Init=ka,n("value","",(function(e,t){return e.setValue(t)}),!0),n("mode",null,(function(e,t){e.doc.modeOption=t,Ao(e)}),!0),n("indentUnit",2,Ao,!0),n("indentWithTabs",!1),n("smartIndent",!0),n("tabSize",4,(function(e){Po(e),Hn(e),dr(e)}),!0),n("lineSeparator",null,(function(e,t){if(e.doc.lineSep=t,t){var n=[],r=e.doc.first;e.doc.iter((function(e){for(var o=0;;){var i=e.text.indexOf(t,o);if(-1==i)break;o=i+t.length,n.push(tt(r,i))}r++}));for(var o=n.length-1;o>=0;o--)gi(e.doc,t,n[o],tt(n[o].line,n[o].ch+t.length))}})),n("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,(function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=ka&&e.refresh()})),n("specialCharPlaceholder",Jt,(function(e){return e.refresh()}),!0),n("electricChars",!0),n("inputStyle",y?"contenteditable":"textarea",(function(){throw new Error("inputStyle can not (yet) be changed in a running editor")}),!0),n("spellcheck",!1,(function(e,t){return e.getInputField().spellcheck=t}),!0),n("autocorrect",!1,(function(e,t){return e.getInputField().autocorrect=t}),!0),n("autocapitalize",!1,(function(e,t){return e.getInputField().autocapitalize=t}),!0),n("rtlMoveVisually",!_),n("wholeLineUpdateBefore",!0),n("theme","default",(function(e){xa(e),mo(e)}),!0),n("keyMap","default",(function(e,t,n){var r=Xi(t),o=n!=ka&&Xi(n);o&&o.detach&&o.detach(e,r),r.attach&&r.attach(e,o||null)})),n("extraKeys",null),n("configureMouse",null),n("lineWrapping",!1,Sa,!0),n("gutters",[],(function(e,t){e.display.gutterSpecs=vo(t,e.options.lineNumbers),mo(e)}),!0),n("fixedGutter",!0,(function(e,t){e.display.gutters.style.left=t?sr(e.display)+"px":"0",e.refresh()}),!0),n("coverGutterNextToScrollbar",!1,(function(e){return Ur(e)}),!0),n("scrollbarStyle","native",(function(e){qr(e),Ur(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)}),!0),n("lineNumbers",!1,(function(e,t){e.display.gutterSpecs=vo(e.options.gutters,t),mo(e)}),!0),n("firstLineNumber",1,mo,!0),n("lineNumberFormatter",(function(e){return e}),mo,!0),n("showCursorWhenSelecting",!1,mr,!0),n("resetSelectionOnContextMenu",!0),n("lineWiseCopyCut",!0),n("pasteLinesPerSelection",!0),n("selectionsMayTouch",!1),n("readOnly",!1,(function(e,t){"nocursor"==t&&(Er(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)})),n("screenReaderLabel",null,(function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)})),n("disableInput",!1,(function(e,t){t||e.display.input.reset()}),!0),n("dragDrop",!0,Ea),n("allowDropFileTypes",null),n("cursorBlinkRate",530),n("cursorScrollMargin",0),n("cursorHeight",1,mr,!0),n("singleCursorHeightPerLine",!0,mr,!0),n("workTime",100),n("workDelay",100),n("flattenSpans",!0,Po,!0),n("addModeClass",!1,Po,!0),n("pollInterval",100),n("undoDepth",200,(function(e,t){return e.doc.history.undoDepth=t})),n("historyEventDelay",1250),n("viewportMargin",10,(function(e){return e.refresh()}),!0),n("maxHighlightLength",1e4,Po,!0),n("moveInputWithCursor",!0,(function(e,t){t||e.display.input.resetPosition()})),n("tabindex",null,(function(e,t){return e.display.input.getField().tabIndex=t||""})),n("autofocus",null),n("direction","ltr",(function(e,t){return e.doc.setDirection(t)}),!0),n("phrases",null)}(Ta),function(e){var t=e.optionHandlers,n=e.helpers={};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,n){var r=this.options,o=r[e];r[e]==n&&"mode"!=e||(r[e]=n,t.hasOwnProperty(e)&&to(this,t[e])(this,n,o),ve(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Xi(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;nn&&(Ma(this,o.head.line,e,!0),n=o.head.line,r==this.doc.sel.primIndex&&Ar(this));else{var i=o.from(),a=o.to(),s=Math.max(n,i.line);n=Math.min(this.lastLine(),a.line-(a.ch?0:1))+1;for(var u=s;u0&&Qo(this.doc,r,new Oo(i,l[r].to()),W)}}})),getTokenAt:function(e,t){return bt(this,e,t)},getLineTokens:function(e,t){return bt(this,tt(e),t,!0)},getTokenTypeAt:function(e){e=ut(this.doc,e);var t,n=pt(this,Ge(this.doc,e.line)),r=0,o=(n.length-1)/2,i=e.ch;if(0==i)t=n[2];else for(;;){var a=r+o>>1;if((a?n[2*a-1]:0)>=i)o=a;else{if(!(n[2*a+1]i&&(e=i,o=!0),r=Ge(this.doc,e)}else r=e;return qn(this,r,{top:0,left:0},t||"page",n||o).top+(o?this.doc.height-Vt(r):0)},defaultTextHeight:function(){return or(this.display)},defaultCharWidth:function(){return ir(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,o){var i,a,s,u=this.display,l=(e=$n(this,ut(this.doc,e))).bottom,c=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),u.sizer.appendChild(t),"over"==r)l=e.top;else if("above"==r||"near"==r){var f=Math.max(u.wrapper.clientHeight,this.doc.height),d=Math.max(u.sizer.clientWidth,u.lineSpace.clientWidth);("above"==r||e.bottom+t.offsetHeight>f)&&e.top>t.offsetHeight?l=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=f&&(l=e.bottom),c+t.offsetWidth>d&&(c=d-t.offsetWidth)}t.style.top=l+"px",t.style.left=t.style.right="","right"==o?(c=u.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==o?c=0:"middle"==o&&(c=(u.sizer.clientWidth-t.offsetWidth)/2),t.style.left=c+"px"),n&&(i=this,a={left:c,top:l,right:c+t.offsetWidth,bottom:l+t.offsetHeight},null!=(s=Mr(i,a)).scrollTop&&Ir(i,s.scrollTop),null!=s.scrollLeft&&zr(i,s.scrollLeft))},triggerOnKeyDown:no(fa),triggerOnKeyPress:no(pa),triggerOnKeyUp:da,triggerOnMouseDown:no(ma),execCommand:function(e){if(na.hasOwnProperty(e))return na[e].call(null,this)},triggerElectric:no((function(e){Da(this,e)})),findPosH:function(e,t,n,r){var o=1;t<0&&(o=-1,t=-t);for(var i=ut(this.doc,e),a=0;a0&&a(t.charAt(n-1));)--n;for(;r.5||this.options.lineWrapping)&&lr(this),ve(this,"refresh",this)})),swapDoc:no((function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),No(this,e),Hn(this),this.display.input.reset(),Pr(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,ln(this,"swapDoc",this,t),t})),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},be(e),e.registerHelper=function(t,r,o){n.hasOwnProperty(t)||(n[t]=e[t]={_global:[]}),n[t][r]=o},e.registerGlobalHelper=function(t,r,o,i){e.registerHelper(t,r,i),n[t]._global.push({pred:o,val:i})}}(Ta);var Ga="iter insert remove copy getEditor constructor".split(" ");for(var $a in Ai.prototype)Ai.prototype.hasOwnProperty($a)&&H(Ga,$a)<0&&(Ta.prototype[$a]=function(e){return function(){return e.apply(this.doc,arguments)}}(Ai.prototype[$a]));return be(Ai),Ta.inputStyles={textarea:Ya,contenteditable:Ha},Ta.defineMode=function(e){Ta.defaults.mode||"null"==e||(Ta.defaults.mode=e),ze.apply(this,arguments)},Ta.defineMIME=function(e,t){Ne[e]=t},Ta.defineMode("null",(function(){return{token:function(e){return e.skipToEnd()}}})),Ta.defineMIME("text/plain","null"),Ta.defineExtension=function(e,t){Ta.prototype[e]=t},Ta.defineDocExtension=function(e,t){Ai.prototype[e]=t},Ta.fromTextArea=function(e,t){if((t=t?z(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var n=P();t.autofocus=n==e||null!=e.getAttribute("autofocus")&&n==document.body}function r(){e.value=s.getValue()}var o;if(e.form&&(de(e.form,"submit",r),!t.leaveSubmitMethodAlone)){var i=e.form;o=i.submit;try{var a=i.submit=function(){r(),i.submit=o,i.submit(),i.submit=a}}catch(e){}}t.finishInit=function(n){n.save=r,n.getTextArea=function(){return e},n.toTextArea=function(){n.toTextArea=isNaN,r(),e.parentNode.removeChild(n.getWrapperElement()),e.style.display="",e.form&&(he(e.form,"submit",r),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=o))}},e.style.display="none";var s=Ta((function(t){return e.parentNode.insertBefore(t,e.nextSibling)}),t);return s},function(e){e.off=he,e.on=de,e.wheelEventPixels=xo,e.Doc=Ai,e.splitLines=Ae,e.countColumn=F,e.findColumn=Y,e.isWordChar=ee,e.Pass=U,e.signal=ve,e.Line=Gt,e.changeEnd=To,e.scrollbarModel=Vr,e.Pos=tt,e.cmpPos=nt,e.modes=Ie,e.mimeModes=Ne,e.resolveMode=Fe,e.getMode=Be,e.modeExtensions=He,e.extendMode=Ue,e.copyState=We,e.startState=qe,e.innerMode=Ve,e.commands=na,e.keyMap=Vi,e.keyName=Zi,e.isModifierKey=$i,e.lookupKey=Gi,e.normalizeKeyMap=Yi,e.StringStream=Ye,e.SharedTextMarker=Ti,e.TextMarker=Ei,e.LineWidget=ki,e.e_preventDefault=we,e.e_stopPropagation=_e,e.e_stop=ke,e.addClass=R,e.contains=A,e.rmClass=S,e.keyNames=Bi}(Ta),Ta.version="5.65.5",Ta}()},function(e,t,n){var r=n(329),o=n(330),i=n(170),a=n(331);e.exports=function(e,t){return r(e)||o(e,t)||i(e,t)||a()},e.exports.__esModule=!0,e.exports.default=e.exports},function(e,t){var n=Array.isArray;e.exports=n},function(e,t,n){var r=n(159),o=n(164),i=n(77),a=n(23),s=n(38),u=n(106),l=n(76),c=n(107),f=Object.prototype.hasOwnProperty;e.exports=function(e){if(null==e)return!0;if(s(e)&&(a(e)||"string"==typeof e||"function"==typeof e.splice||u(e)||c(e)||i(e)))return!e.length;var t=o(e);if("[object Map]"==t||"[object Set]"==t)return!e.size;if(l(e))return!r(e).length;for(var n in e)if(f.call(e,n))return!1;return!0}},function(e,t,n){var r=n(266),o=n(267),i=n(147),a=n(268);e.exports=function(e,t){return r(e)||o(e,t)||i(e,t)||a()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){"use strict"; /** * Copyright (c) 2013-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */e.exports=function(e,t,n,r,o,i,a,s){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,i,a,s],c=0;(u=new Error(t.replace(/%s/g,(function(){return l[c++]})))).name="Invariant Violation"}throw u.framesToPop=1,u}}},function(e,t){function n(){return e.exports=n=Object.assign||function(e){for(var t=1;tg.EOF;){try{switch(n){case g.MEDIA_SYM:this._media(),this._skipCruft();break;case g.PAGE_SYM:this._page(),this._skipCruft();break;case g.FONT_FACE_SYM:this._font_face(),this._skipCruft();break;case g.KEYFRAMES_SYM:this._keyframes(),this._skipCruft();break;case g.VIEWPORT_SYM:this._viewport(),this._skipCruft();break;case g.DOCUMENT_SYM:this._document(),this._skipCruft();break;case g.SUPPORTS_SYM:this._supports(),this._skipCruft();break;case g.UNKNOWN_SYM:if(r.get(),this.options.strict)throw new o("Unknown @ rule.",r.LT(0).startLine,r.LT(0).startCol);for(this.fire({type:"error",error:null,message:"Unknown @ rule: "+r.LT(0).value+".",line:r.LT(0).startLine,col:r.LT(0).startCol}),e=0;r.advance([g.LBRACE,g.RBRACE])===g.LBRACE;)e++;for(;e;)r.advance([g.RBRACE]),e--;break;case g.S:this._readWhitespace();break;default:if(!this._ruleset())switch(n){case g.CHARSET_SYM:throw t=r.LT(1),this._charset(!1),new o("@charset not allowed here.",t.startLine,t.startCol);case g.IMPORT_SYM:throw t=r.LT(1),this._import(!1),new o("@import not allowed here.",t.startLine,t.startCol);case g.NAMESPACE_SYM:throw t=r.LT(1),this._namespace(!1),new o("@namespace not allowed here.",t.startLine,t.startCol);default:r.get(),this._unexpectedToken(r.token())}}}catch(e){if(!(e instanceof o)||this.options.strict)throw e;this.fire({type:"error",error:e,message:e.message,line:e.line,col:e.col})}n=r.peek()}n!==g.EOF&&this._unexpectedToken(r.token()),this.fire("endstylesheet")},_charset:function(e){var t,n,r,o=this._tokenStream;o.match(g.CHARSET_SYM)&&(n=o.token().startLine,r=o.token().startCol,this._readWhitespace(),o.mustMatch(g.STRING),t=o.token().value,this._readWhitespace(),o.mustMatch(g.SEMICOLON),!1!==e&&this.fire({type:"charset",charset:t,line:n,col:r}))},_import:function(e){var t,n,r,o=this._tokenStream;o.mustMatch(g.IMPORT_SYM),n=o.token(),this._readWhitespace(),o.mustMatch([g.STRING,g.URI]),t=o.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/,"$1"),this._readWhitespace(),r=this._media_query_list(),o.mustMatch(g.SEMICOLON),this._readWhitespace(),!1!==e&&this.fire({type:"import",uri:t,media:r,line:n.startLine,col:n.startCol})},_namespace:function(e){var t,n,r,o,i=this._tokenStream;i.mustMatch(g.NAMESPACE_SYM),t=i.token().startLine,n=i.token().startCol,this._readWhitespace(),i.match(g.IDENT)&&(r=i.token().value,this._readWhitespace()),i.mustMatch([g.STRING,g.URI]),o=i.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/,"$1"),this._readWhitespace(),i.mustMatch(g.SEMICOLON),this._readWhitespace(),!1!==e&&this.fire({type:"namespace",prefix:r,uri:o,line:t,col:n})},_supports:function(e){var t,n,r=this._tokenStream;if(r.match(g.SUPPORTS_SYM)){for(t=r.token().startLine,n=r.token().startCol,this._readWhitespace(),this._supports_condition(),this._readWhitespace(),r.mustMatch(g.LBRACE),this._readWhitespace(),!1!==e&&this.fire({type:"startsupports",line:t,col:n});this._ruleset(););r.mustMatch(g.RBRACE),this._readWhitespace(),this.fire({type:"endsupports",line:t,col:n})}},_supports_condition:function(){var e,t=this._tokenStream;if(t.match(g.IDENT))"not"===(e=t.token().value.toLowerCase())?(t.mustMatch(g.S),this._supports_condition_in_parens()):t.unget();else for(this._supports_condition_in_parens(),this._readWhitespace();t.peek()===g.IDENT;)"and"!==(e=t.LT(1).value.toLowerCase())&&"or"!==e||(t.mustMatch(g.IDENT),this._readWhitespace(),this._supports_condition_in_parens(),this._readWhitespace())},_supports_condition_in_parens:function(){var e=this._tokenStream;e.match(g.LPAREN)?(this._readWhitespace(),e.match(g.IDENT)?"not"===e.token().value.toLowerCase()?(this._readWhitespace(),this._supports_condition(),this._readWhitespace(),e.mustMatch(g.RPAREN)):(e.unget(),this._supports_declaration_condition(!1)):(this._supports_condition(),this._readWhitespace(),e.mustMatch(g.RPAREN))):this._supports_declaration_condition()},_supports_declaration_condition:function(e){var t=this._tokenStream;!1!==e&&t.mustMatch(g.LPAREN),this._readWhitespace(),this._declaration(),t.mustMatch(g.RPAREN)},_media:function(){var e,t,n,r=this._tokenStream;for(r.mustMatch(g.MEDIA_SYM),e=r.token().startLine,t=r.token().startCol,this._readWhitespace(),n=this._media_query_list(),r.mustMatch(g.LBRACE),this._readWhitespace(),this.fire({type:"startmedia",media:n,line:e,col:t});;)if(r.peek()===g.PAGE_SYM)this._page();else if(r.peek()===g.FONT_FACE_SYM)this._font_face();else if(r.peek()===g.VIEWPORT_SYM)this._viewport();else if(r.peek()===g.DOCUMENT_SYM)this._document();else if(r.peek()===g.SUPPORTS_SYM)this._supports();else if(r.peek()===g.MEDIA_SYM)this._media();else if(!this._ruleset())break;r.mustMatch(g.RBRACE),this._readWhitespace(),this.fire({type:"endmedia",media:n,line:e,col:t})},_media_query_list:function(){var e=this._tokenStream,t=[];for(this._readWhitespace(),e.peek()!==g.IDENT&&e.peek()!==g.LPAREN||t.push(this._media_query());e.match(g.COMMA);)this._readWhitespace(),t.push(this._media_query());return t},_media_query:function(){var e=this._tokenStream,t=null,n=null,r=null,o=[];if(e.match(g.IDENT)&&("only"!==(n=e.token().value.toLowerCase())&&"not"!==n?(e.unget(),n=null):r=e.token()),this._readWhitespace(),e.peek()===g.IDENT?(t=this._media_type(),null===r&&(r=e.token())):e.peek()===g.LPAREN&&(null===r&&(r=e.LT(1)),o.push(this._media_expression())),null===t&&0===o.length)return null;for(this._readWhitespace();e.match(g.IDENT);)"and"!==e.token().value.toLowerCase()&&this._unexpectedToken(e.token()),this._readWhitespace(),o.push(this._media_expression());return new u(n,t,o,r.startLine,r.startCol)},_media_type:function(){return this._media_feature()},_media_expression:function(){var e,t,n=this._tokenStream,r=null;return n.mustMatch(g.LPAREN),e=this._media_feature(),this._readWhitespace(),n.match(g.COLON)&&(this._readWhitespace(),t=n.LT(1),r=this._expression()),n.mustMatch(g.RPAREN),this._readWhitespace(),new s(e,r?new i(r,t.startLine,t.startCol):null)},_media_feature:function(){var e=this._tokenStream;return this._readWhitespace(),e.mustMatch(g.IDENT),i.fromToken(e.token())},_page:function(){var e,t,n=this._tokenStream,r=null,o=null;n.mustMatch(g.PAGE_SYM),e=n.token().startLine,t=n.token().startCol,this._readWhitespace(),n.match(g.IDENT)&&"auto"===(r=n.token().value).toLowerCase()&&this._unexpectedToken(n.token()),n.peek()===g.COLON&&(o=this._pseudo_page()),this._readWhitespace(),this.fire({type:"startpage",id:r,pseudo:o,line:e,col:t}),this._readDeclarations(!0,!0),this.fire({type:"endpage",id:r,pseudo:o,line:e,col:t})},_margin:function(){var e,t,n=this._tokenStream,r=this._margin_sym();return!!r&&(e=n.token().startLine,t=n.token().startCol,this.fire({type:"startpagemargin",margin:r,line:e,col:t}),this._readDeclarations(!0),this.fire({type:"endpagemargin",margin:r,line:e,col:t}),!0)},_margin_sym:function(){var e=this._tokenStream;return e.match([g.TOPLEFTCORNER_SYM,g.TOPLEFT_SYM,g.TOPCENTER_SYM,g.TOPRIGHT_SYM,g.TOPRIGHTCORNER_SYM,g.BOTTOMLEFTCORNER_SYM,g.BOTTOMLEFT_SYM,g.BOTTOMCENTER_SYM,g.BOTTOMRIGHT_SYM,g.BOTTOMRIGHTCORNER_SYM,g.LEFTTOP_SYM,g.LEFTMIDDLE_SYM,g.LEFTBOTTOM_SYM,g.RIGHTTOP_SYM,g.RIGHTMIDDLE_SYM,g.RIGHTBOTTOM_SYM])?i.fromToken(e.token()):null},_pseudo_page:function(){var e=this._tokenStream;return e.mustMatch(g.COLON),e.mustMatch(g.IDENT),e.token().value},_font_face:function(){var e,t,n=this._tokenStream;n.mustMatch(g.FONT_FACE_SYM),e=n.token().startLine,t=n.token().startCol,this._readWhitespace(),this.fire({type:"startfontface",line:e,col:t}),this._readDeclarations(!0),this.fire({type:"endfontface",line:e,col:t})},_viewport:function(){var e,t,n=this._tokenStream;n.mustMatch(g.VIEWPORT_SYM),e=n.token().startLine,t=n.token().startCol,this._readWhitespace(),this.fire({type:"startviewport",line:e,col:t}),this._readDeclarations(!0),this.fire({type:"endviewport",line:e,col:t})},_document:function(){var e,t=this._tokenStream,n=[],r="";for(t.mustMatch(g.DOCUMENT_SYM),e=t.token(),/^@\-([^\-]+)\-/.test(e.value)&&(r=RegExp.$1),this._readWhitespace(),n.push(this._document_function());t.match(g.COMMA);)this._readWhitespace(),n.push(this._document_function());t.mustMatch(g.LBRACE),this._readWhitespace(),this.fire({type:"startdocument",functions:n,prefix:r,line:e.startLine,col:e.startCol});for(var o=!0;o;)switch(t.peek()){case g.PAGE_SYM:this._page();break;case g.FONT_FACE_SYM:this._font_face();break;case g.VIEWPORT_SYM:this._viewport();break;case g.MEDIA_SYM:this._media();break;case g.KEYFRAMES_SYM:this._keyframes();break;case g.DOCUMENT_SYM:this._document();break;default:o=Boolean(this._ruleset())}t.mustMatch(g.RBRACE),e=t.token(),this._readWhitespace(),this.fire({type:"enddocument",functions:n,prefix:r,line:e.startLine,col:e.startCol})},_document_function:function(){var e,t=this._tokenStream;return t.match(g.URI)?(e=t.token().value,this._readWhitespace()):e=this._function(),e},_operator:function(e){var t=this._tokenStream,n=null;return(t.match([g.SLASH,g.COMMA])||e&&t.match([g.PLUS,g.STAR,g.MINUS]))&&(n=t.token(),this._readWhitespace()),n?f.fromToken(n):null},_combinator:function(){var e,t=this._tokenStream,n=null;return t.match([g.PLUS,g.GREATER,g.TILDE])&&(e=t.token(),n=new a(e.value,e.startLine,e.startCol),this._readWhitespace()),n},_unary_operator:function(){var e=this._tokenStream;return e.match([g.MINUS,g.PLUS])?e.token().value:null},_property:function(){var e,t,n,r,o=this._tokenStream,i=null,a=null;return o.peek()===g.STAR&&this.options.starHack&&(o.get(),a=(t=o.token()).value,n=t.startLine,r=t.startCol),o.match(g.IDENT)&&("_"===(e=(t=o.token()).value).charAt(0)&&this.options.underscoreHack&&(a="_",e=e.substring(1)),i=new l(e,a,n||t.startLine,r||t.startCol),this._readWhitespace()),i},_ruleset:function(){var e,t=this._tokenStream;try{e=this._selectors_group()}catch(e){if(!(e instanceof o)||this.options.strict)throw e;if(this.fire({type:"error",error:e,message:e.message,line:e.line,col:e.col}),t.advance([g.RBRACE])!==g.RBRACE)throw e;return!0}return e&&(this.fire({type:"startrule",selectors:e,line:e[0].line,col:e[0].col}),this._readDeclarations(!0),this.fire({type:"endrule",selectors:e,line:e[0].line,col:e[0].col})),e},_selectors_group:function(){var e,t=this._tokenStream,n=[];if(null!==(e=this._selector()))for(n.push(e);t.match(g.COMMA);)this._readWhitespace(),null!==(e=this._selector())?n.push(e):this._unexpectedToken(t.LT(1));return n.length?n:null},_selector:function(){var e=this._tokenStream,t=[],n=null,r=null,o=null;if(null===(n=this._simple_selector_sequence()))return null;for(t.push(n);;)if(null!==(r=this._combinator()))t.push(r),null===(n=this._simple_selector_sequence())?this._unexpectedToken(e.LT(1)):t.push(n);else{if(!this._readWhitespace())break;o=new a(e.token().value,e.token().startLine,e.token().startCol),r=this._combinator(),null===(n=this._simple_selector_sequence())?null!==r&&this._unexpectedToken(e.LT(1)):(null!==r?t.push(r):t.push(o),t.push(n))}return new d(t,t[0].line,t[0].col)},_simple_selector_sequence:function(){var e,t,n=this._tokenStream,r=null,o=[],i="",a=[function(){return n.match(g.HASH)?new h(n.token().value,"id",n.token().startLine,n.token().startCol):null},this._class,this._attrib,this._pseudo,this._negation],s=0,u=a.length,l=null;for(e=n.LT(1).startLine,t=n.LT(1).startCol,(r=this._type_selector())||(r=this._universal()),null!==r&&(i+=r);n.peek()!==g.S;){for(;s1&&e.unget()),null)},_class:function(){var e,t=this._tokenStream;return t.match(g.DOT)?(t.mustMatch(g.IDENT),e=t.token(),new h("."+e.value,"class",e.startLine,e.startCol-1)):null},_element_name:function(){var e,t=this._tokenStream;return t.match(g.IDENT)?(e=t.token(),new h(e.value,"elementName",e.startLine,e.startCol)):null},_namespace_prefix:function(){var e=this._tokenStream,t="";return e.LA(1)!==g.PIPE&&e.LA(2)!==g.PIPE||(e.match([g.IDENT,g.STAR])&&(t+=e.token().value),e.mustMatch(g.PIPE),t+="|"),t.length?t:null},_universal:function(){var e,t=this._tokenStream,n="";return(e=this._namespace_prefix())&&(n+=e),t.match(g.STAR)&&(n+="*"),n.length?n:null},_attrib:function(){var e,t,n=this._tokenStream,r=null;return n.match(g.LBRACKET)?(r=(t=n.token()).value,r+=this._readWhitespace(),(e=this._namespace_prefix())&&(r+=e),n.mustMatch(g.IDENT),r+=n.token().value,r+=this._readWhitespace(),n.match([g.PREFIXMATCH,g.SUFFIXMATCH,g.SUBSTRINGMATCH,g.EQUALS,g.INCLUDES,g.DASHMATCH])&&(r+=n.token().value,r+=this._readWhitespace(),n.mustMatch([g.IDENT,g.STRING]),r+=n.token().value,r+=this._readWhitespace()),n.mustMatch(g.RBRACKET),new h(r+"]","attribute",t.startLine,t.startCol)):null},_pseudo:function(){var e,t,n=this._tokenStream,r=null,i=":";if(n.match(g.COLON)){if(n.match(g.COLON)&&(i+=":"),n.match(g.IDENT)?(r=n.token().value,e=n.token().startLine,t=n.token().startCol-i.length):n.peek()===g.FUNCTION&&(e=n.LT(1).startLine,t=n.LT(1).startCol-i.length,r=this._functional_pseudo()),!r){var a=n.LT(1).startLine,s=n.LT(0).startCol;throw new o("Expected a `FUNCTION` or `IDENT` after colon at line "+a+", col "+s+".",a,s)}r=new h(i+r,"pseudo",e,t)}return r},_functional_pseudo:function(){var e=this._tokenStream,t=null;return e.match(g.FUNCTION)&&(t=e.token().value,t+=this._readWhitespace(),t+=this._expression(),e.mustMatch(g.RPAREN),t+=")"),t},_expression:function(){for(var e=this._tokenStream,t="";e.match([g.PLUS,g.MINUS,g.DIMENSION,g.NUMBER,g.STRING,g.IDENT,g.LENGTH,g.FREQ,g.ANGLE,g.TIME,g.RESOLUTION,g.SLASH]);)t+=e.token().value,t+=this._readWhitespace();return t.length?t:null},_negation:function(){var e,t,n,r=this._tokenStream,o="",i=null;return r.match(g.NOT)&&(o=r.token().value,e=r.token().startLine,t=r.token().startCol,o+=this._readWhitespace(),o+=n=this._negation_arg(),o+=this._readWhitespace(),r.match(g.RPAREN),o+=r.token().value,(i=new h(o,"not",e,t)).args.push(n)),i},_negation_arg:function(){var e,t,n=this._tokenStream,r=[this._type_selector,this._universal,function(){return n.match(g.HASH)?new h(n.token().value,"id",n.token().startLine,n.token().startCol):null},this._class,this._attrib,this._pseudo],o=null,i=0,a=r.length;for(e=n.LT(1).startLine,t=n.LT(1).startCol;i0?new c(t,t[0].line,t[0].col):null},_term:function(e){var t,n,r,o,i=this._tokenStream,a=null,s=null,u=null;return null!==(t=this._unary_operator())&&(r=i.token().startLine,o=i.token().startCol),i.peek()===g.IE_FUNCTION&&this.options.ieFilters?(a=this._ie_function(),null===t&&(r=i.token().startLine,o=i.token().startCol)):e&&i.match([g.LPAREN,g.LBRACE,g.LBRACKET])?(s=(n=i.token()).endChar,a=n.value+this._expr(e).text,null===t&&(r=i.token().startLine,o=i.token().startCol),i.mustMatch(g.type(s)),a+=s,this._readWhitespace()):i.match([g.NUMBER,g.PERCENTAGE,g.LENGTH,g.ANGLE,g.TIME,g.FREQ,g.STRING,g.IDENT,g.URI,g.UNICODE_RANGE])?(a=i.token().value,null===t&&(r=i.token().startLine,o=i.token().startCol,u=f.fromToken(i.token())),this._readWhitespace()):null===(n=this._hexcolor())?(null===t&&(r=i.LT(1).startLine,o=i.LT(1).startCol),null===a&&(a=i.LA(3)===g.EQUALS&&this.options.ieFilters?this._ie_function():this._function())):(a=n.value,null===t&&(r=n.startLine,o=n.startCol)),null!==u?u:null!==a?new f(null!==t?t+a:a,r,o):null},_function:function(){var e,t=this._tokenStream,n=null;if(t.match(g.FUNCTION)){if(n=t.token().value,this._readWhitespace(),n+=this._expr(!0),this.options.ieFilters&&t.peek()===g.EQUALS)do{for(this._readWhitespace()&&(n+=t.token().value),t.LA(0)===g.COMMA&&(n+=t.token().value),t.match(g.IDENT),n+=t.token().value,t.match(g.EQUALS),n+=t.token().value,e=t.peek();e!==g.COMMA&&e!==g.S&&e!==g.RPAREN;)t.get(),n+=t.token().value,e=t.peek()}while(t.match([g.COMMA,g.S]));t.match(g.RPAREN),n+=")",this._readWhitespace()}return n},_ie_function:function(){var e,t=this._tokenStream,n=null;if(t.match([g.IE_FUNCTION,g.FUNCTION])){n=t.token().value;do{for(this._readWhitespace()&&(n+=t.token().value),t.LA(0)===g.COMMA&&(n+=t.token().value),t.match(g.IDENT),n+=t.token().value,t.match(g.EQUALS),n+=t.token().value,e=t.peek();e!==g.COMMA&&e!==g.S&&e!==g.RPAREN;)t.get(),n+=t.token().value,e=t.peek()}while(t.match([g.COMMA,g.S]));t.match(g.RPAREN),n+=")",this._readWhitespace()}return n},_hexcolor:function(){var e,t=this._tokenStream,n=null;if(t.match(g.HASH)){if(e=(n=t.token()).value,!/#[a-f0-9]{3,6}/i.test(e))throw new o("Expected a hex color but found '"+e+"' at line "+n.startLine+", col "+n.startCol+".",n.startLine,n.startCol);this._readWhitespace()}return n},_keyframes:function(){var e,t,n,r=this._tokenStream,o="";for(r.mustMatch(g.KEYFRAMES_SYM),e=r.token(),/^@\-([^\-]+)\-/.test(e.value)&&(o=RegExp.$1),this._readWhitespace(),n=this._keyframe_name(),this._readWhitespace(),r.mustMatch(g.LBRACE),this.fire({type:"startkeyframes",name:n,prefix:o,line:e.startLine,col:e.startCol}),this._readWhitespace(),t=r.peek();t===g.IDENT||t===g.PERCENTAGE;)this._keyframe_rule(),this._readWhitespace(),t=r.peek();this.fire({type:"endkeyframes",name:n,prefix:o,line:e.startLine,col:e.startCol}),this._readWhitespace(),r.mustMatch(g.RBRACE),this._readWhitespace()},_keyframe_name:function(){var e=this._tokenStream;return e.mustMatch([g.IDENT,g.STRING]),i.fromToken(e.token())},_keyframe_rule:function(){var e=this._key_list();this.fire({type:"startkeyframerule",keys:e,line:e[0].line,col:e[0].col}),this._readDeclarations(!0),this.fire({type:"endkeyframerule",keys:e,line:e[0].line,col:e[0].col})},_key_list:function(){var e=this._tokenStream,t=[];for(t.push(this._key()),this._readWhitespace();e.match(g.COMMA);)this._readWhitespace(),t.push(this._key()),this._readWhitespace();return t},_key:function(){var e,t=this._tokenStream;if(t.match(g.PERCENTAGE))return i.fromToken(t.token());if(t.match(g.IDENT)){if(e=t.token(),/from|to/i.test(e.value))return i.fromToken(e);t.unget()}this._unexpectedToken(t.LT(1))},_skipCruft:function(){for(;this._tokenStream.match([g.S,g.CDO,g.CDC]););},_readDeclarations:function(e,t){var n,r=this._tokenStream;this._readWhitespace(),e&&r.mustMatch(g.LBRACE),this._readWhitespace();try{for(;;){if(r.match(g.SEMICOLON)||t&&this._margin());else{if(!this._declaration())break;if(!r.match(g.SEMICOLON))break}this._readWhitespace()}r.mustMatch(g.RBRACE),this._readWhitespace()}catch(e){if(!(e instanceof o)||this.options.strict)throw e;if(this.fire({type:"error",error:e,message:e.message,line:e.line,col:e.col}),(n=r.advance([g.SEMICOLON,g.RBRACE]))===g.SEMICOLON)this._readDeclarations(!1,t);else if(n!==g.RBRACE)throw e}},_readWhitespace:function(){for(var e=this._tokenStream,t="";e.match(g.S);)t+=e.token().value;return t},_unexpectedToken:function(e){throw new o("Unexpected token '"+e.value+"' at line "+e.startLine+", col "+e.startCol+".",e.startLine,e.startCol)},_verifyEnd:function(){this._tokenStream.LA(1)!==g.EOF&&this._unexpectedToken(this._tokenStream.LT(1))},_validateProperty:function(e,t){m.validate(e,t)},parse:function(e){this._tokenStream=new v(e,g),this._stylesheet()},parseStyleSheet:function(e){return this.parse(e)},parseMediaQuery:function(e){this._tokenStream=new v(e,g);var t=this._media_query();return this._verifyEnd(),t},parsePropertyValue:function(e){this._tokenStream=new v(e,g),this._readWhitespace();var t=this._expr();return this._readWhitespace(),this._verifyEnd(),t},parseRule:function(e){this._tokenStream=new v(e,g),this._readWhitespace();var t=this._ruleset();return this._readWhitespace(),this._verifyEnd(),t},parseSelector:function(e){this._tokenStream=new v(e,g),this._readWhitespace();var t=this._selector();return this._readWhitespace(),this._verifyEnd(),t},parseStyleAttribute:function(e){e+="}",this._tokenStream=new v(e,g),this._readDeclarations()}};for(e in n)Object.prototype.hasOwnProperty.call(n,e)&&(t[e]=n[e]);return t}()},function(e,t,n){var r=n(283);e.exports=function(e,t){if(null==e)return{};var n,o,i=r(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o-1:!!c&&r(e,t,n)>-1}},function(e,t){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}},function(e,t,n){var r=n(32).Symbol;e.exports=r},function(e,t){e.exports=function(e,t){return e===t||e!=e&&t!=t}},function(e,t){var n=/^(?:0|[1-9]\d*)$/;e.exports=function(e,t){var r=typeof e;return!!(t=null==t?9007199254740991:t)&&("number"==r||"symbol"!=r&&n.test(e))&&e>-1&&e%1==0&&e=200){var v=t?null:s(e);if(v)return u(v);d=!1,c=a,h=new r}else h=t?[]:p;e:for(;++l=0;g--)if(c.canDragSource(n[g])){v=n[g];break}if(null!==v){var m=null;u&&(i("function"==typeof l,"When clientOffset is provided, getSourceClientOffset must be a function."),m=l(v));var y=f.getSource(v).beginDrag(c,v);i(a(y),"Item must be an object."),f.pinSource(v);var b=f.getSourceType(v);return{type:t.BEGIN_DRAG,payload:{itemType:b,item:y,sourceId:v,clientOffset:u||null,sourceClientOffset:m||null,isSourcePublic:!!s}}}},publishDragSource:function(){if(e.getMonitor().isDragging())return{type:t.PUBLISH_DRAG_SOURCE}},hover:function(n,r){var a=(void 0===r?{}:r).clientOffset;i(Array.isArray(n),"Expected targetIds to be an array.");var s=n.slice(0),u=e.getMonitor(),l=e.getRegistry();i(u.isDragging(),"Cannot call hover while not dragging."),i(!u.didDrop(),"Cannot call hover after drop.");for(var c=0;c=0;c--){f=s[c];var h=l.getTargetType(f);o.default(h,p)||s.splice(c,1)}for(var v=0,g=s;v"},{name:"COMMA",text:","},{name:"TILDE",text:"~"},{name:"NOT"},{name:"TOPLEFTCORNER_SYM",text:"@top-left-corner"},{name:"TOPLEFT_SYM",text:"@top-left"},{name:"TOPCENTER_SYM",text:"@top-center"},{name:"TOPRIGHT_SYM",text:"@top-right"},{name:"TOPRIGHTCORNER_SYM",text:"@top-right-corner"},{name:"BOTTOMLEFTCORNER_SYM",text:"@bottom-left-corner"},{name:"BOTTOMLEFT_SYM",text:"@bottom-left"},{name:"BOTTOMCENTER_SYM",text:"@bottom-center"},{name:"BOTTOMRIGHT_SYM",text:"@bottom-right"},{name:"BOTTOMRIGHTCORNER_SYM",text:"@bottom-right-corner"},{name:"LEFTTOP_SYM",text:"@left-top"},{name:"LEFTMIDDLE_SYM",text:"@left-middle"},{name:"LEFTBOTTOM_SYM",text:"@left-bottom"},{name:"RIGHTTOP_SYM",text:"@right-top"},{name:"RIGHTMIDDLE_SYM",text:"@right-middle"},{name:"RIGHTBOTTOM_SYM",text:"@right-bottom"},{name:"RESOLUTION",state:"media"},{name:"IE_FUNCTION"},{name:"CHAR"},{name:"PIPE",text:"|"},{name:"SLASH",text:"/"},{name:"MINUS",text:"-"},{name:"STAR",text:"*"},{name:"LBRACE",endChar:"}",text:"{"},{name:"RBRACE",text:"}"},{name:"LBRACKET",endChar:"]",text:"["},{name:"RBRACKET",text:"]"},{name:"EQUALS",text:"="},{name:"COLON",text:":"},{name:"SEMICOLON",text:";"},{name:"LPAREN",endChar:")",text:"("},{name:"RPAREN",text:")"},{name:"DOT",text:"."}];!function(){var e=[],t=Object.create(null);r.UNKNOWN=-1,r.unshift({name:"EOF"});for(var n=0,o=r.length;n=43)}})).catch((function(){return!1}))}(e).then((function(e){return f=e}))}function v(e){var t=d[e.name],n={};n.promise=new a((function(e,t){n.resolve=e,n.reject=t})),t.deferredOperations.push(n),t.dbReady?t.dbReady=t.dbReady.then((function(){return n.promise})):t.dbReady=n.promise}function g(e){var t=d[e.name].deferredOperations.pop();if(t)return t.resolve(),t.promise}function m(e,t){var n=d[e.name].deferredOperations.pop();if(n)return n.reject(t),n.promise}function y(e,t){return new a((function(n,r){if(d[e.name]=d[e.name]||{forages:[],db:null,dbReady:null,deferredOperations:[]},e.db){if(!t)return n(e.db);v(e),e.db.close()}var i=[e.name];t&&i.push(e.version);var a=o.open.apply(o,i);t&&(a.onupgradeneeded=function(t){var n=a.result;try{n.createObjectStore(e.storeName),t.oldVersion<=1&&n.createObjectStore("local-forage-detect-blob-support")}catch(n){if("ConstraintError"!==n.name)throw n;console.warn('The database "'+e.name+'" has been upgraded from version '+t.oldVersion+" to version "+t.newVersion+', but the storage "'+e.storeName+'" already exists.')}}),a.onerror=function(e){e.preventDefault(),r(a.error)},a.onsuccess=function(){var t=a.result;t.onversionchange=function(e){e.target.close()},n(t),g(e)}}))}function b(e){return y(e,!1)}function w(e){return y(e,!0)}function _(e,t){if(!e.db)return!0;var n=!e.db.objectStoreNames.contains(e.storeName),r=e.versione.db.version;if(r&&(e.version!==t&&console.warn('The database "'+e.name+"\" can't be downgraded from version "+e.db.version+" to version "+e.version+"."),e.version=e.db.version),o||n){if(n){var i=e.db.version+1;i>e.version&&(e.version=i)}return!0}return!1}function x(e){return i([function(e){for(var t=e.length,n=new ArrayBuffer(t),r=new Uint8Array(n),o=0;o0&&(!e.db||"InvalidStateError"===o.name||"NotFoundError"===o.name))return a.resolve().then((function(){if(!e.db||"NotFoundError"===o.name&&!e.db.objectStoreNames.contains(e.storeName)&&e.version<=e.db.version)return e.db&&(e.version=e.db.version+1),w(e)})).then((function(){return function(e){v(e);for(var t=d[e.name],n=t.forages,r=0;r>4,c[u++]=(15&r)<<4|o>>2,c[u++]=(3&o)<<6|63&i;return l}function P(e){var t,n=new Uint8Array(e),r="";for(t=0;t>2],r+=S[(3&n[t])<<4|n[t+1]>>4],r+=S[(15&n[t+1])<<2|n[t+2]>>6],r+=S[63&n[t+2]];return n.length%3==2?r=r.substring(0,r.length-1)+"=":n.length%3==1&&(r=r.substring(0,r.length-2)+"=="),r}var R={serialize:function(e,t){var n="";if(e&&(n=L.call(e)),e&&("[object ArrayBuffer]"===n||e.buffer&&"[object ArrayBuffer]"===L.call(e.buffer))){var r,o="__lfsc__:";e instanceof ArrayBuffer?(r=e,o+="arbf"):(r=e.buffer,"[object Int8Array]"===n?o+="si08":"[object Uint8Array]"===n?o+="ui08":"[object Uint8ClampedArray]"===n?o+="uic8":"[object Int16Array]"===n?o+="si16":"[object Uint16Array]"===n?o+="ur16":"[object Int32Array]"===n?o+="si32":"[object Uint32Array]"===n?o+="ui32":"[object Float32Array]"===n?o+="fl32":"[object Float64Array]"===n?o+="fl64":t(new Error("Failed to get type for BinaryArray"))),t(o+P(r))}else if("[object Blob]"===n){var i=new FileReader;i.onload=function(){var n="~~local_forage_type~"+e.type+"~"+P(this.result);t("__lfsc__:blob"+n)},i.readAsArrayBuffer(e)}else try{t(JSON.stringify(e))}catch(n){console.error("Couldn't convert value into a JSON string: ",e),t(null,n)}},deserialize:function(e){if("__lfsc__:"!==e.substring(0,j))return JSON.parse(e);var t,n=e.substring(M),r=e.substring(j,M);if("blob"===r&&T.test(n)){var o=n.match(T);t=o[1],n=n.substring(o[0].length)}var a=A(n);switch(r){case"arbf":return a;case"blob":return i([a],{type:t});case"si08":return new Int8Array(a);case"ui08":return new Uint8Array(a);case"uic8":return new Uint8ClampedArray(a);case"si16":return new Int16Array(a);case"ur16":return new Uint16Array(a);case"si32":return new Int32Array(a);case"ui32":return new Uint32Array(a);case"fl32":return new Float32Array(a);case"fl64":return new Float64Array(a);default:throw new Error("Unkown type: "+r)}},stringToBuffer:A,bufferToString:P}; /* * Includes code from: * * base64-arraybuffer * https://github.com/niklasvh/base64-arraybuffer * * Copyright (c) 2012 Niklas von Hertzen * Licensed under the MIT license. */function D(e,t,n,r){e.executeSql("CREATE TABLE IF NOT EXISTS "+t.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],n,r)}function I(e,t,n,r,o,i){e.executeSql(n,r,o,(function(e,a){a.code===a.SYNTAX_ERR?e.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name = ?",[t.storeName],(function(e,s){s.rows.length?i(e,a):D(e,t,(function(){e.executeSql(n,r,o,i)}),i)}),i):i(e,a)}),i)}function N(e,t,n,r){var o=this;e=l(e);var i=new a((function(i,a){o.ready().then((function(){void 0===t&&(t=null);var s=t,u=o._dbInfo;u.serializer.serialize(t,(function(t,l){l?a(l):u.db.transaction((function(n){I(n,u,"INSERT OR REPLACE INTO "+u.storeName+" (key, value) VALUES (?, ?)",[e,t],(function(){i(s)}),(function(e,t){a(t)}))}),(function(t){if(t.code===t.QUOTA_ERR){if(r>0)return void i(N.apply(o,[e,s,n,r-1]));a(t)}}))}))})).catch(a)}));return s(i,n),i}function z(e){return new a((function(t,n){e.transaction((function(r){r.executeSql("SELECT name FROM sqlite_master WHERE type='table' AND name <> '__WebKitDatabaseInfoTable__'",[],(function(n,r){for(var o=[],i=0;i0}var U={_driver:"localStorageWrapper",_initStorage:function(e){var t={};if(e)for(var n in e)t[n]=e[n];return t.keyPrefix=B(e,this._defaultConfig),H()?(this._dbInfo=t,t.serializer=R,a.resolve()):a.reject()},_support:function(){try{return"undefined"!=typeof localStorage&&"setItem"in localStorage&&!!localStorage.setItem}catch(e){return!1}}(),iterate:function(e,t){var n=this,r=n.ready().then((function(){for(var t=n._dbInfo,r=t.keyPrefix,o=r.length,i=localStorage.length,a=1,s=0;s=0;n--){var r=localStorage.key(n);0===r.indexOf(e)&&localStorage.removeItem(r)}}));return s(n,e),n},length:function(e){var t=this.keys().then((function(e){return e.length}));return s(t,e),t},key:function(e,t){var n=this,r=n.ready().then((function(){var t,r=n._dbInfo;try{t=localStorage.key(e)}catch(e){t=null}return t&&(t=t.substring(r.keyPrefix.length)),t}));return s(r,t),r},keys:function(e){var t=this,n=t.ready().then((function(){for(var e=t._dbInfo,n=localStorage.length,r=[],o=0;o=0;t--){var n=localStorage.key(t);0===n.indexOf(e)&&localStorage.removeItem(n)}})):a.reject("Invalid arguments"),t),r}},W=function(e,t){for(var n,r,o=e.length,i=0;i-1&&e%1==0&&e<=9007199254740991}},function(e,t,n){(function(e){var r=n(32),o=n(292),i=t&&!t.nodeType&&t,a=i&&"object"==typeof e&&e&&!e.nodeType&&e,s=a&&a.exports===i?r.Buffer:void 0,u=(s?s.isBuffer:void 0)||o;e.exports=u}).call(this,n(57)(e))},function(e,t,n){var r=n(293),o=n(108),i=n(294),a=i&&i.isTypedArray,s=a?o(a):r;e.exports=s},function(e,t){e.exports=function(e){return function(t){return e(t)}}},function(e,t,n){var r=n(296),o=n(318),i=n(75),a=n(23),s=n(321);e.exports=function(e){return"function"==typeof e?e:null==e?i:"object"==typeof e?a(e)?o(e[0],e[1]):r(e):s(e)}},function(e,t,n){var r=n(303),o=n(33);e.exports=function e(t,n,i,a,s){return t===n||(null==t||null==n||!o(t)&&!o(n)?t!=t&&n!=n:r(t,n,i,a,e,s))}},function(e,t){e.exports=function(e){var t=-1,n=Array(e.size);return e.forEach((function(e){n[++t]=e})),n}},function(e,t){e.exports=function(e,t){for(var n=-1,r=null==e?0:e.length,o=0,i=[];++nt===e.identifier)||e.changedTouches&&(0,r.findInArray)(e.changedTouches,e=>t===e.identifier)},t.getTouchIdentifier=function(e){if(e.targetTouches&&e.targetTouches[0])return e.targetTouches[0].identifier;if(e.changedTouches&&e.changedTouches[0])return e.changedTouches[0].identifier},t.getTranslation=u,t.innerHeight=function(e){let t=e.clientHeight;const n=e.ownerDocument.defaultView.getComputedStyle(e);return t-=(0,r.int)(n.paddingTop),t-=(0,r.int)(n.paddingBottom),t},t.innerWidth=function(e){let t=e.clientWidth;const n=e.ownerDocument.defaultView.getComputedStyle(e);return t-=(0,r.int)(n.paddingLeft),t-=(0,r.int)(n.paddingRight),t},t.matchesSelector=s,t.matchesSelectorAndParentsTo=function(e,t,n){let r=e;do{if(s(r,t))return!0;if(r===n)return!1;r=r.parentNode}while(r);return!1},t.offsetXYFromParent=function(e,t,n){const r=t===t.ownerDocument.body?{left:0,top:0}:t.getBoundingClientRect(),o=(e.clientX+t.scrollLeft-r.left)/n,i=(e.clientY+t.scrollTop-r.top)/n;return{x:o,y:i}},t.outerHeight=function(e){let t=e.clientHeight;const n=e.ownerDocument.defaultView.getComputedStyle(e);return t+=(0,r.int)(n.borderTopWidth),t+=(0,r.int)(n.borderBottomWidth),t},t.outerWidth=function(e){let t=e.clientWidth;const n=e.ownerDocument.defaultView.getComputedStyle(e);return t+=(0,r.int)(n.borderLeftWidth),t+=(0,r.int)(n.borderRightWidth),t},t.removeClassName=c,t.removeEvent=function(e,t,n,r){if(!e)return;const o={capture:!0,...r};e.removeEventListener?e.removeEventListener(t,n,o):e.detachEvent?e.detachEvent("on"+t,n):e["on"+t]=null},t.removeUserSelectStyles=function(e){if(!e)return;try{if(e.body&&c(e.body,"react-draggable-transparent-selection"),e.selection)e.selection.empty();else{const t=(e.defaultView||window).getSelection();t&&"Caret"!==t.type&&t.removeAllRanges()}}catch(e){}};var r=n(80),o=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var n=i(t);if(n&&n.has(e))return n.get(e);var r={},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var s=o?Object.getOwnPropertyDescriptor(e,a):null;s&&(s.get||s.set)?Object.defineProperty(r,a,s):r[a]=e[a]}r.default=e,n&&n.set(e,r);return r}(n(334));function i(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,n=new WeakMap;return(i=function(e){return e?n:t})(e)}let a="";function s(e,t){return a||(a=(0,r.findInArray)(["matches","webkitMatchesSelector","mozMatchesSelector","msMatchesSelector","oMatchesSelector"],(function(t){return(0,r.isFunction)(e[t])}))),!!(0,r.isFunction)(e[a])&&e[a](t)}function u(e,t,n){let{x:r,y:o}=e,i="translate(".concat(r).concat(n,",").concat(o).concat(n,")");if(t){const e="".concat("string"==typeof t.x?t.x:t.x+n),r="".concat("string"==typeof t.y?t.y:t.y+n);i="translate(".concat(e,", ").concat(r,")")+i}return i}function l(e,t){e.classList?e.classList.add(t):e.className.match(new RegExp("(?:^|\\s)".concat(t,"(?!\\S)")))||(e.className+=" ".concat(t))}function c(e,t){e.classList?e.classList.remove(t):e.className=e.className.replace(new RegExp("(?:^|\\s)".concat(t,"(?!\\S)"),"g"),"")}},function(e,t,n){var r=n(174);e.exports=function(e,t){return!!(null==e?0:e.length)&&r(e,t,0)>-1}},function(e,t){e.exports=function(e,t,n){for(var r=-1,o=null==e?0:e.length;++r0&&i(c)?n>1?e(c,n-1,i,a,s):r(s,c):a||(s[s.length]=c)}return s}},function(e,t,n){"use strict"; /** * Copyright 2015, Yahoo! Inc. * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. */var r={childContextTypes:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i=Object.defineProperty,a=Object.getOwnPropertyNames,s=Object.getOwnPropertySymbols,u=Object.getOwnPropertyDescriptor,l=Object.getPrototypeOf,c=l&&l(Object);e.exports=function e(t,n,f){if("string"!=typeof n){if(c){var d=l(n);d&&d!==c&&e(t,d,f)}var p=a(n);s&&(p=p.concat(s(n)));for(var h=0;hc);f++){var d=e.getLine(l++);s=null==s?d:s+"\n"+d}u*=2,t.lastIndex=n.ch;var p=t.exec(s);if(p){var h=s.slice(0,p.index).split("\n"),v=p[0].split("\n"),g=n.line+h.length-1,m=h[h.length-1].length;return{from:r(g,m),to:r(g+v.length-1,1==v.length?m+v[0].length:v[v.length-1].length),match:p}}}}function u(e,t,n){for(var r,o=0;o<=e.length;){t.lastIndex=o;var i=t.exec(e);if(!i)break;var a=i.index+i[0].length;if(a>e.length-n)break;(!r||a>r.index+r[0].length)&&(r=i),o=i.index+1}return r}function l(e,t,n){t=o(t,"g");for(var i=n.line,a=n.ch,s=e.firstLine();i>=s;i--,a=-1){var l=e.getLine(i),c=u(l,t,a<0?0:l.length-a);if(c)return{from:r(i,c.index),to:r(i,c.index+c[0].length),match:c}}}function c(e,t,n){if(!i(t))return l(e,t,n);t=o(t,"gm");for(var a,s=1,c=e.getLine(n.line).length-n.ch,f=n.line,d=e.firstLine();f>=d;){for(var p=0;p=d;p++){var h=e.getLine(f--);a=null==a?h:h+"\n"+a}s*=2;var v=u(a,t,c);if(v){var g=a.slice(0,v.index).split("\n"),m=v[0].split("\n"),y=f+g.length,b=g[g.length-1].length;return{from:r(y,b),to:r(y+m.length-1,1==m.length?b+m[0].length:m[m.length-1].length),match:v}}}}function f(e,t,n,r){if(e.length==t.length)return n;for(var o=0,i=n+Math.max(0,e.length-t.length);;){if(o==i)return o;var a=o+i>>1,s=r(e.slice(0,a)).length;if(s==n)return a;s>n?i=a:o=a+1}}function d(e,o,i,a){if(!o.length)return null;var s=a?t:n,u=s(o).split(/\r|\n\r?/);e:for(var l=i.line,c=i.ch,d=e.lastLine()+1-u.length;l<=d;l++,c=0){var p=e.getLine(l).slice(c),h=s(p);if(1==u.length){var v=h.indexOf(u[0]);if(-1==v)continue e;return i=f(p,h,v,s)+c,{from:r(l,f(p,h,v,s)+c),to:r(l,f(p,h,v+u[0].length,s)+c)}}var g=h.length-u[0].length;if(h.slice(g)==u[0]){for(var m=1;m=d;l--,c=-1){var p=e.getLine(l);c>-1&&(p=p.slice(0,c));var h=s(p);if(1==u.length){var v=h.lastIndexOf(u[0]);if(-1==v)continue e;return{from:r(l,f(p,h,v,s)),to:r(l,f(p,h,v+u[0].length,s))}}var g=u[u.length-1];if(h.slice(0,g.length)==g){var m=1;for(i=l-u.length+1;m(this.doc.getLine(n.line)||"").length&&(n.ch=0,n.line++)),0!=e.cmpPos(n,this.doc.clipPos(n))))return this.atOccurrence=!1;var o=this.matches(t,n);if(this.afterEmptyMatch=o&&0==e.cmpPos(o.from,o.to),o)return this.pos=o,this.atOccurrence=!0,this.pos.match||!0;var i=r(t?this.doc.firstLine():this.doc.lastLine()+1,0);return this.pos={from:i,to:i},this.atOccurrence=!1},from:function(){if(this.atOccurrence)return this.pos.from},to:function(){if(this.atOccurrence)return this.pos.to},replace:function(t,n){if(this.atOccurrence){var o=e.splitLines(t);this.doc.replaceRange(o,this.pos.from,this.pos.to,n),this.pos.to=r(this.pos.from.line+o.length-1,o[o.length-1].length+(1==o.length?this.pos.from.ch:0))}}},e.defineExtension("getSearchCursor",(function(e,t,n){return new h(this.doc,e,t,n)})),e.defineDocExtension("getSearchCursor",(function(e,t,n){return new h(this,e,t,n)})),e.defineExtension("selectMatches",(function(t,n){for(var r=[],o=this.getSearchCursor(t,this.getCursor("from"),n);o.findNext()&&!(e.cmpPos(o.to(),this.getCursor("to"))>0);)r.push({anchor:o.from(),head:o.to()});r.length&&this.setSelections(r,0)}))}(n(21))},function(e,t,n){ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/LICENSE !function(e){"use strict";function t(e){for(var t={},n=0;n*\/]/.test(n)?x(null,"select-op"):"."==n&&e.match(/^-?[_a-z][_a-z0-9-]*/i)?x("qualifier","qualifier"):/[:;{}\[\]\(\)]/.test(n)?x(null,n):e.match(/^[\w-.]+(?=\()/)?(/^(url(-prefix)?|domain|regexp)$/i.test(e.current())&&(t.tokenize=O),x("variable callee","variable")):/[\w\\\-]/.test(n)?(e.eatWhile(/[\w\\\-]/),x("property","word")):x(null,null):/[\d.]/.test(e.peek())?(e.eatWhile(/[\w.%]/),x("number","unit")):e.match(/^-[\w\\\-]*/)?(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?x("variable-2","variable-definition"):x("variable-2","variable")):e.match(/^\w+-/)?x("meta","meta"):void 0}function C(e){return function(t,n){for(var r,o=!1;null!=(r=t.next());){if(r==e&&!o){")"==e&&t.backUp(1);break}o=!o&&"\\"==r}return(r==e||!o&&")"!=e)&&(n.tokenize=null),x("string","string")}}function O(e,t){return e.next(),e.match(/^\s*[\"\')]/,!1)?t.tokenize=null:t.tokenize=C(")"),x(null,"(")}function E(e,t,n){this.type=e,this.indent=t,this.prev=n}function S(e,t,n,r){return e.context=new E(n,t.indentation()+(!1===r?0:a),e.context),n}function T(e){return e.context.prev&&(e.context=e.context.prev),e.context.type}function j(e,t,n){return A[n.context.type](e,t,n)}function M(e,t,n,r){for(var o=r||1;o>0;o--)n.context=n.context.prev;return j(e,t,n)}function L(e){var t=e.current().toLowerCase();i=m.hasOwnProperty(t)?"atom":g.hasOwnProperty(t)?"keyword":"variable"}var A={top:function(e,t,n){if("{"==e)return S(n,t,"block");if("}"==e&&n.context.prev)return T(n);if(w&&/@component/i.test(e))return S(n,t,"atComponentBlock");if(/^@(-moz-)?document$/i.test(e))return S(n,t,"documentTypes");if(/^@(media|supports|(-moz-)?document|import)$/i.test(e))return S(n,t,"atBlock");if(/^@(font-face|counter-style)/i.test(e))return n.stateArg=e,"restricted_atBlock_before";if(/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(e))return"keyframes";if(e&&"@"==e.charAt(0))return S(n,t,"at");if("hash"==e)i="builtin";else if("word"==e)i="tag";else{if("variable-definition"==e)return"maybeprop";if("interpolation"==e)return S(n,t,"interpolation");if(":"==e)return"pseudo";if(y&&"("==e)return S(n,t,"parens")}return n.context.type},block:function(e,t,n){if("word"==e){var r=t.current().toLowerCase();return d.hasOwnProperty(r)?(i="property","maybeprop"):p.hasOwnProperty(r)?(i=_?"string-2":"property","maybeprop"):y?(i=t.match(/^\s*:(?:\s|$)/,!1)?"property":"tag","block"):(i+=" error","maybeprop")}return"meta"==e?"block":y||"hash"!=e&&"qualifier"!=e?A.top(e,t,n):(i="error","block")},maybeprop:function(e,t,n){return":"==e?S(n,t,"prop"):j(e,t,n)},prop:function(e,t,n){if(";"==e)return T(n);if("{"==e&&y)return S(n,t,"propBlock");if("}"==e||"{"==e)return M(e,t,n);if("("==e)return S(n,t,"parens");if("hash"!=e||/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(t.current())){if("word"==e)L(t);else if("interpolation"==e)return S(n,t,"interpolation")}else i+=" error";return"prop"},propBlock:function(e,t,n){return"}"==e?T(n):"word"==e?(i="property","maybeprop"):n.context.type},parens:function(e,t,n){return"{"==e||"}"==e?M(e,t,n):")"==e?T(n):"("==e?S(n,t,"parens"):"interpolation"==e?S(n,t,"interpolation"):("word"==e&&L(t),"parens")},pseudo:function(e,t,n){return"meta"==e?"pseudo":"word"==e?(i="variable-3",n.context.type):j(e,t,n)},documentTypes:function(e,t,n){return"word"==e&&u.hasOwnProperty(t.current())?(i="tag",n.context.type):A.atBlock(e,t,n)},atBlock:function(e,t,n){if("("==e)return S(n,t,"atBlock_parens");if("}"==e||";"==e)return M(e,t,n);if("{"==e)return T(n)&&S(n,t,y?"block":"top");if("interpolation"==e)return S(n,t,"interpolation");if("word"==e){var r=t.current().toLowerCase();i="only"==r||"not"==r||"and"==r||"or"==r?"keyword":l.hasOwnProperty(r)?"attribute":c.hasOwnProperty(r)?"property":f.hasOwnProperty(r)?"keyword":d.hasOwnProperty(r)?"property":p.hasOwnProperty(r)?_?"string-2":"property":m.hasOwnProperty(r)?"atom":g.hasOwnProperty(r)?"keyword":"error"}return n.context.type},atComponentBlock:function(e,t,n){return"}"==e?M(e,t,n):"{"==e?T(n)&&S(n,t,y?"block":"top",!1):("word"==e&&(i="error"),n.context.type)},atBlock_parens:function(e,t,n){return")"==e?T(n):"{"==e||"}"==e?M(e,t,n,2):A.atBlock(e,t,n)},restricted_atBlock_before:function(e,t,n){return"{"==e?S(n,t,"restricted_atBlock"):"word"==e&&"@counter-style"==n.stateArg?(i="variable","restricted_atBlock_before"):j(e,t,n)},restricted_atBlock:function(e,t,n){return"}"==e?(n.stateArg=null,T(n)):"word"==e?(i="@font-face"==n.stateArg&&!h.hasOwnProperty(t.current().toLowerCase())||"@counter-style"==n.stateArg&&!v.hasOwnProperty(t.current().toLowerCase())?"error":"property","maybeprop"):"restricted_atBlock"},keyframes:function(e,t,n){return"word"==e?(i="variable","keyframes"):"{"==e?S(n,t,"top"):j(e,t,n)},at:function(e,t,n){return";"==e?T(n):"{"==e||"}"==e?M(e,t,n):("word"==e?i="tag":"hash"==e&&(i="builtin"),"at")},interpolation:function(e,t,n){return"}"==e?T(n):"{"==e||";"==e?M(e,t,n):("word"==e?i="variable":"variable"!=e&&"("!=e&&")"!=e&&(i="error"),"interpolation")}};return{startState:function(e){return{tokenize:null,state:r?"block":"top",stateArg:null,context:new E(r?"block":"top",e||0,null)}},token:function(e,t){if(!t.tokenize&&e.eatSpace())return null;var n=(t.tokenize||k)(e,t);return n&&"object"==typeof n&&(o=n[1],n=n[0]),i=n,"comment"!=o&&(t.state=A[t.state](o,e,t)),i},indent:function(e,t){var n=e.context,r=t&&t.charAt(0),o=n.indent;return"prop"!=n.type||"}"!=r&&")"!=r||(n=n.prev),n.prev&&("}"!=r||"block"!=n.type&&"top"!=n.type&&"interpolation"!=n.type&&"restricted_atBlock"!=n.type?(")"!=r||"parens"!=n.type&&"atBlock_parens"!=n.type)&&("{"!=r||"at"!=n.type&&"atBlock"!=n.type)||(o=Math.max(0,n.indent-a)):o=(n=n.prev).indent),o},electricChars:"}",blockCommentStart:"/*",blockCommentEnd:"*/",blockCommentContinue:" * ",lineComment:b,fold:"brace"}}));var n=["domain","regexp","url","url-prefix"],r=t(n),o=["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"],i=t(o),a=["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid","orientation","device-pixel-ratio","min-device-pixel-ratio","max-device-pixel-ratio","pointer","any-pointer","hover","any-hover","prefers-color-scheme","dynamic-range","video-dynamic-range"],s=t(a),u=["landscape","portrait","none","coarse","fine","on-demand","hover","interlace","progressive","dark","light","standard","high"],l=t(u),c=["align-content","align-items","align-self","alignment-adjust","alignment-baseline","all","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backdrop-filter","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-position-x","background-position-y","background-repeat","background-size","baseline-shift","binding","bleed","block-size","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-content","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-family","font-feature-settings","font-kerning","font-language-override","font-optical-sizing","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-gap","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-gap","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","inset","inset-block","inset-block-end","inset-block-start","inset-inline","inset-inline-end","inset-inline-start","isolation","justify-content","justify-items","justify-self","left","letter-spacing","line-break","line-height","line-height-step","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","offset","offset-anchor","offset-distance","offset-path","offset-position","offset-rotate","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","place-content","place-items","place-self","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotate","rotation","rotation-point","row-gap","ruby-align","ruby-overhang","ruby-position","ruby-span","scale","scroll-behavior","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-type","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-skip-ink","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-orientation","text-outline","text-overflow","text-rendering","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","touch-action","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","translate","unicode-bidi","user-select","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","paint-order","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode"],f=t(c),d=["accent-color","aspect-ratio","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","content-visibility","margin-block","margin-block-end","margin-block-start","margin-inline","margin-inline-end","margin-inline-start","overflow-anchor","overscroll-behavior","padding-block","padding-block-end","padding-block-start","padding-inline","padding-inline-end","padding-inline-start","scroll-snap-stop","scrollbar-3d-light-color","scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-track-color","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","shape-inside","zoom"],p=t(d),h=t(["font-display","font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"]),v=t(["additive-symbols","fallback","negative","pad","prefix","range","speak-as","suffix","symbols","system"]),g=["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkgrey","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkslategrey","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dimgrey","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightgrey","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightslategrey","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","slategrey","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"],m=t(g),y=["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","auto-flow","avoid","avoid-column","avoid-page","avoid-region","axis-pan","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","blur","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","brightness","bullets","button","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","color","color-burn","color-dodge","column","column-reverse","compact","condensed","conic-gradient","contain","content","contents","content-box","context-menu","continuous","contrast","copy","counter","counters","cover","crop","cross","crosshair","cubic-bezier","currentcolor","cursive","cyclic","darken","dashed","decimal","decimal-leading-zero","default","default-button","dense","destination-atop","destination-in","destination-out","destination-over","devanagari","difference","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","drop-shadow","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","exclusion","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fill-box","fixed","flat","flex","flex-end","flex-start","footnotes","forwards","from","geometricPrecision","georgian","grayscale","graytext","grid","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hard-light","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","hue","hue-rotate","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-grid","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","lighten","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","luminosity","malayalam","manipulation","match","matrix","matrix3d","media-play-button","media-slider","media-sliderthumb","media-volume-slider","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","multiple_mask_images","multiply","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","opacity","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","pinch-zoom","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeating-conic-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row","row-resize","row-reverse","rtl","run-in","running","s-resize","sans-serif","saturate","saturation","scale","scale3d","scaleX","scaleY","scaleZ","screen","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","self-start","self-end","semi-condensed","semi-expanded","separate","sepia","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","soft-light","solid","somali","source-atop","source-in","source-out","source-over","space","space-around","space-between","space-evenly","spell-out","square","square-button","start","static","status-bar","stretch","stroke","stroke-box","sub","subpixel-antialiased","svg_masks","super","sw-resize","symbolic","symbols","system-ui","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","transform","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","unidirectional-pan","unset","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","view-box","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","wrap","wrap-reverse","x-large","x-small","xor","xx-large","xx-small"],b=t(y),w=n.concat(o).concat(a).concat(u).concat(c).concat(d).concat(g).concat(y);function _(e,t){for(var n,r=!1;null!=(n=e.next());){if(r&&"/"==n){t.tokenize=null;break}r="*"==n}return["comment","comment"]}e.registerHelper("hintWords","css",w),e.defineMIME("text/css",{documentTypes:r,mediaTypes:i,mediaFeatures:s,mediaValueKeywords:l,propertyKeywords:f,nonStandardPropertyKeywords:p,fontProperties:h,counterDescriptors:v,colorKeywords:m,valueKeywords:b,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=_,_(e,t))}},name:"css"}),e.defineMIME("text/x-scss",{mediaTypes:i,mediaFeatures:s,mediaValueKeywords:l,propertyKeywords:f,nonStandardPropertyKeywords:p,colorKeywords:m,valueKeywords:b,fontProperties:h,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=_,_(e,t)):["operator","operator"]},":":function(e){return!!e.match(/^\s*\{/,!1)&&[null,null]},$:function(e){return e.match(/^[\w-]+/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"]},"#":function(e){return!!e.eat("{")&&[null,"interpolation"]}},name:"css",helperType:"scss"}),e.defineMIME("text/x-less",{mediaTypes:i,mediaFeatures:s,mediaValueKeywords:l,propertyKeywords:f,nonStandardPropertyKeywords:p,colorKeywords:m,valueKeywords:b,fontProperties:h,allowNested:!0,lineComment:"//",tokenHooks:{"/":function(e,t){return e.eat("/")?(e.skipToEnd(),["comment","comment"]):e.eat("*")?(t.tokenize=_,_(e,t)):["operator","operator"]},"@":function(e){return e.eat("{")?[null,"interpolation"]:!e.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i,!1)&&(e.eatWhile(/[\w\\\-]/),e.match(/^\s*:/,!1)?["variable-2","variable-definition"]:["variable-2","variable"])},"&":function(){return["atom","atom"]}},name:"css",helperType:"less"}),e.defineMIME("text/x-gss",{documentTypes:r,mediaTypes:i,mediaFeatures:s,propertyKeywords:f,nonStandardPropertyKeywords:p,fontProperties:h,counterDescriptors:v,colorKeywords:m,valueKeywords:b,supportsAtComponent:!0,tokenHooks:{"/":function(e,t){return!!e.eat("*")&&(t.tokenize=_,_(e,t))}},name:"css",helperType:"gss"})}(n(21))},function(e,t,n){"use strict";e.exports=s;var r=n(30),o=n(194),i=n(34),a=n(88);function s(e,t,n,a){var u,l=a||{};if(r.call(this,e,t,n,i.PROPERTY_VALUE_PART_TYPE),this.type="unknown",/^([+\-]?[\d\.]+)([a-z]+)$/i.test(e))switch(this.type="dimension",this.value=+RegExp.$1,this.units=RegExp.$2,this.units.toLowerCase()){case"em":case"rem":case"ex":case"px":case"cm":case"mm":case"in":case"pt":case"pc":case"ch":case"vh":case"vw":case"vmax":case"vmin":this.type="length";break;case"fr":this.type="grid";break;case"deg":case"rad":case"grad":case"turn":this.type="angle";break;case"ms":case"s":this.type="time";break;case"hz":case"khz":this.type="frequency";break;case"dpi":case"dpcm":this.type="resolution"}else/^([+\-]?[\d\.]+)%$/i.test(e)?(this.type="percentage",this.value=+RegExp.$1):/^([+\-]?\d+)$/i.test(e)?(this.type="integer",this.value=+RegExp.$1):/^([+\-]?[\d\.]+)$/i.test(e)?(this.type="number",this.value=+RegExp.$1):/^#([a-f0-9]{3,6})/i.test(e)?(this.type="color",3===(u=RegExp.$1).length?(this.red=parseInt(u.charAt(0)+u.charAt(0),16),this.green=parseInt(u.charAt(1)+u.charAt(1),16),this.blue=parseInt(u.charAt(2)+u.charAt(2),16)):(this.red=parseInt(u.substring(0,2),16),this.green=parseInt(u.substring(2,4),16),this.blue=parseInt(u.substring(4,6),16))):/^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/i.test(e)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3):/^rgb\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(e)?(this.type="color",this.red=255*+RegExp.$1/100,this.green=255*+RegExp.$2/100,this.blue=255*+RegExp.$3/100):/^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*([\d\.]+)\s*\)/i.test(e)?(this.type="color",this.red=+RegExp.$1,this.green=+RegExp.$2,this.blue=+RegExp.$3,this.alpha=+RegExp.$4):/^rgba\(\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(e)?(this.type="color",this.red=255*+RegExp.$1/100,this.green=255*+RegExp.$2/100,this.blue=255*+RegExp.$3/100,this.alpha=+RegExp.$4):/^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)/i.test(e)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100):/^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*([\d\.]+)\s*\)/i.test(e)?(this.type="color",this.hue=+RegExp.$1,this.saturation=+RegExp.$2/100,this.lightness=+RegExp.$3/100,this.alpha=+RegExp.$4):/^url\(("([^\\"]|\\.)*")\)/i.test(e)?(this.type="uri",this.uri=s.parseString(RegExp.$1)):/^([^\(]+)\(/i.test(e)?(this.type="function",this.name=RegExp.$1,this.value=e):/^"([^\n\r\f\\"]|\\\r\n|\\[^\r0-9a-f]|\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?)*"/i.test(e)||/^'([^\n\r\f\\']|\\\r\n|\\[^\r0-9a-f]|\\[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?)*'/i.test(e)?(this.type="string",this.value=s.parseString(e)):o[e.toLowerCase()]?(this.type="color",u=o[e.toLowerCase()].substring(1),this.red=parseInt(u.substring(0,2),16),this.green=parseInt(u.substring(2,4),16),this.blue=parseInt(u.substring(4,6),16)):/^[,\/]$/.test(e)?(this.type="operator",this.value=e):/^-?[a-z_\u00A0-\uFFFF][a-z0-9\-_\u00A0-\uFFFF]*$/i.test(e)&&(this.type="identifier",this.value=e);this.wasIdent=Boolean(l.ident)}s.prototype=new r,s.prototype.constructor=s,s.parseString=function(e){return(e=e.slice(1,-1)).replace(/\\(\r\n|[^\r0-9a-f]|[0-9a-f]{1,6}(\r\n|[ \n\r\t\f])?)/gi,(function(e,t){if(/^(\n|\r\n|\r|\f)$/.test(t))return"";var n=/^[0-9a-f]{1,6}/i.exec(t);if(n){var r=parseInt(n[0],16);return String.fromCodePoint?String.fromCodePoint(r):String.fromCharCode(r)}return t}))},s.serializeString=function(e){return'"'+e.replace(/["\r\n\f]/g,(function(e,t){return'"'===t?"\\"+t:"\\"+(String.codePointAt?String.codePointAt(0):String.charCodeAt(0)).toString(16)+" "}))+'"'},s.fromToken=function(e){return new s(e.value,e.startLine,e.startCol,{ident:e.type===a.IDENT})}},function(e,t,n){"use strict";e.exports=i;var r=n(30),o=n(34);function i(e,t,n,i,a){r.call(this,n,i,a,o.SELECTOR_PART_TYPE),this.elementName=e,this.modifiers=t}i.prototype=new r,i.prototype.constructor=i},function(e,t,n){"use strict";function r(e){this._input=e.replace(/(\r\n?|\n)/g,"\n"),this._line=1,this._col=1,this._cursor=0}e.exports=r,r.prototype={constructor:r,getCol:function(){return this._col},getLine:function(){return this._line},eof:function(){return this._cursor===this._input.length},peek:function(e){var t=null;return e=void 0===e?1:e,this._cursorn&&(r="[ "+r+" ]"),r}))},i.alt=function(){var e=Array.prototype.slice.call(arguments).map(i.cast);return 1===e.length?e[0]:new i((function(t){var n,r=!1;for(n=0;!r&&nn&&(r="[ "+r+" ]"),r}))},i.many=function(e){var t=Array.prototype.slice.call(arguments,1).reduce((function(e,t){if(t.expand){var r=n(132);e.push.apply(e,r.complex[t.expand].options)}else e.push(i.cast(t));return e}),[]);!0===e&&(e=t.map((function(){return!0})));var r=new i((function(n){var r=[],o=0,i=0,a=function(s){for(var u=0;u0;for(var s=0;sr&&(o="[ "+o+" ]"),o}));return r.options=t,r},i.andand=function(){var e=Array.prototype.slice.call(arguments);return e.unshift(!0),i.many.apply(i,e)},i.oror=function(){var e=Array.prototype.slice.call(arguments);return e.unshift(!1),i.many.apply(i,e)},i.prototype={constructor:i,match:function(){throw new Error("unimplemented")},toString:function(){throw new Error("unimplemented")},func:function(){return this.match.bind(this)},then:function(e){return i.seq(this,e)},or:function(e){return i.alt(this,e)},andand:function(e){return i.many(!0,this,e)},oror:function(e){return i.many(!1,this,e)},star:function(){return this.braces(0,1/0,"*")},plus:function(){return this.braces(1,1/0,"+")},question:function(){return this.braces(0,1,"?")},hash:function(){return this.braces(1,1/0,"#",i.cast(","))},braces:function(e,t,n,r){var o=this,a=r?r.then(this):this;return n||(n="{"+e+","+t+"}"),new i((function(n){var i;for(i=0;i0&&r?a.match(n):o.match(n));i++);return i>=e}),(function(){return o.toString(i.prec.MOD)+n}))}}},function(e,t,n){"use strict";var r,o,i=e.exports,a=n(131);r=i,o={isLiteral:function(e,t){var n,r,o=e.text.toString().toLowerCase(),i=t.split(" | "),a=!1;for(n=0,r=i.length;n":"xx-small | x-small | small | medium | large | x-large | xx-large","":"scroll-position | contents | ","":function(e){return this[""](e)&&!/^(unset|initial|inherit|will-change|auto|scroll-position|contents)$/i.test(e)},"":function(e){return"angle"===e.type},"":"scroll | fixed | local","":"attr()","":"inset() | circle() | ellipse() | polygon()","":" | | none","":"none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset","":" | thin | medium | thick","":"padding-box | border-box | content-box","":"","":function(e){return"color"===e.type||"transparent"===String(e)||"currentColor"===String(e)},"":function(e){return"color"===e.type},"":"content()","":"fill-available | -moz-available | -webkit-fill-available | max-content | -moz-max-content | -webkit-max-content | min-content | -moz-min-content | -webkit-min-content | fit-content | -moz-fit-content | -webkit-fit-content","":function(e){return"function"===e.type&&/^[A-Z0-9]{4}$/i.test(e)},"":"blur() | brightness() | contrast() | custom() | drop-shadow() | grayscale() | hue-rotate() | invert() | opacity() | saturate() | sepia()","":"","":"row | row-reverse | column | column-reverse","":"","":"","":"nowrap | wrap | wrap-reverse","":" | | | ","":"normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded","":"normal | italic | oblique","":"small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps","":"normal | small-caps","":"normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900","":"serif | sans-serif | cursive | fantasy | monospace","":" | fill-box | stroke-box | view-box","":function(e){return"angle"===e.type&&"deg"===e.units},"":function(e){return"function"===e.type&&/^(?:\-(?:ms|moz|o|webkit)\-)?(?:repeating\-)?(?:radial\-|linear\-)?gradient/i.test(e)},"":"cielab() | cielch() | cielchab() | icc-color() | icc-named-color()","":function(e){return"identifier"===e.type||e.wasIdent},"":function(e){return this[""](e)&&!this[""](e)},"":"","":function(e){return"integer"===e.type},"":function(e){return!("function"!==e.type||!/^(?:\-(?:ms|moz|o|webkit)\-)?calc/i.test(e))||"length"===e.type||"number"===e.type||"integer"===e.type||"0"===String(e)},"":function(e){return"integer"===e.type},"":" | | | normal","":" | | auto","":function(e){return this[""](e)&&e.value>=1},"":function(e){return(this[""](e)||this[""](e))&&("0"===String(e)||"function"===e.type||e.value>=0)},"":function(e){return(this[""](e)||this[""](e))&&("0"===String(e)||"function"===e.type||e.value>=0)},"":function(e){return"number"===e.type||this[""](e)},"":function(e){return this[""](e)&&e.value>=0&&e.value<=1},"":"","":function(e){return"percentage"===e.type||"0"===String(e)},"":"smaller | larger","":"rect() | inset-rect()","":" | margin-box","":"normal | reverse | alternate | alternate-reverse","":function(e){return this[""](e)&&/^-?[a-z_][-a-z0-9_]+$/i.test(e)&&!/^(none|unset|initial|inherit)$/i.test(e)},"":function(e){return"string"===e.type},"