( $str, $pos, $span ) ) ); $pos += $span; break; } throw new Exception( sprintf( 'Unknown symbol "%s"', $next ) ); } } while ( ! empty( $stack ) ) { $o2 = array_pop( $stack ); if ( '(' === $o2 || ')' === $o2 ) { throw new Exception( 'Mismatched parentheses' ); } $output[] = array( 'op', $o2 ); } $this->tokens = $output; } /** * Get the plural form for a number. * * Caches the value for repeated calls. * * @since 4.9.0 * * @param int $num Number to get plural form for. * @return int Plural form value. */ public function get( $num ) { if ( isset( $this->cache[ $num ] ) ) { return $this->cache[ $num ]; } $this->cache[ $num ] = $this->execute( $num ); return $this->cache[ $num ]; } /** * Execute the plural form function. * * @since 4.9.0 * * @param int $n Variable "n" to substitute. * @return int Plural form value. */ public function execute( $n ) { $stack = array(); $i = 0; $total = count( $this->tokens ); while ( $i < $total ) { $next = $this->tokens[ $i ]; $i++; if ( 'var' === $next[0] ) { $stack[] = $n; continue; } elseif ( 'value' === $next[0] ) { $stack[] = $next[1]; continue; } // Only operators left. switch ( $next[1] ) { case '%': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 % $v2; break; case '||': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 || $v2; break; case '&&': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 && $v2; break; case '<': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 < $v2; break; case '<=': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 <= $v2; break; case '>': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 > $v2; break; case '>=': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 >= $v2; break; case '!=': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 != $v2; break; case '==': $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 == $v2; break; case '?:': $v3 = array_pop( $stack ); $v2 = array_pop( $stack ); $v1 = array_pop( $stack ); $stack[] = $v1 ? $v2 : $v3; break; default: throw new Exception( sprintf( 'Unknown operator "%s"', $next[1] ) ); } } if ( count( $stack ) !== 1 ) { throw new Exception( 'Too many values remaining on the stack' ); } return (int) $stack[0]; } } ffffttieand' conjunction becomes 'Sullie, Pattie and me'. * [ 'Sullie', 'Pattie', 'me' ] with 'or' conjunction becomes 'Sullie, Pattie or me'. * * @since 1.8.0 * * @param array $list A list of words or phrases to link together. * @param string $conjunction Coordinating conjunction to use for last word or phrase (usually – and, or). * The string is expected to be translatable. * * @return string Linked words and/or phrases. */ function wpforms_conjunct( $list, $conjunction ) { $last_chunk = array_pop( $list ); return $list ? sprintf( '%s %s %s', implode( ', ', $list ), $conjunction, $last_chunk ) : $last_chunk; } /** * Get the current URL. * * @since 1.0.0 * @since 1.7.2 Refactored based on the `home_url` function. * * @return string */ function wpforms_current_url() { $parsed_home_url = wp_parse_url( home_url() ); $url = $parsed_home_url['scheme'] . '://' . $parsed_home_url['host']; if ( ! empty( $parsed_home_url['port'] ) ) { $url .= ':' . $parsed_home_url['port']; } // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $url .= wp_unslash( $_SERVER['REQUEST_URI'] ); return esc_url_raw( $url ); } /** * Add UTM tags to a link that allows detecting traffic sources for our or partners' websites. * * @since 1.7.5 * * @param string $link Link to which you need to add UTM tags. * @param string $medium The page or location description. Check your current page and try to find * and use an already existing medium for links otherwise, use a page name. * @param string $content The feature's name, the button's content, the link's text, or something * else that describes the element that contains the link. * @param string $term Additional information for the content that makes the link more unique. * * @return string */ function wpforms_utm_link( $link, $medium, $content = '', $term = '' ) { add_query_arg( array_filter( [ 'utm_campaign' => wpforms()->is_pro() ? 'plugin' : 'liteplugin', 'utm_source' => strpos( $link, 'https://wpforms.com' ) === 0 ? 'WordPress' : 'wpformsplugin', 'utm_medium' => rawurlencode( $medium ), 'utm_content' => rawurlencode( $content ), 'utm_term' => rawurlencode( $term ), 'utm_locale' => wpforms_sanitize_key( get_locale() ), ] ), $link ); } /** * Modify the default USer-Agent generated by wp_remote_*() to include additional information. * * @since 1.7.5.2 * * @return string */ function wpforms_get_default_user_agent() { $license_type = wpforms()->is_pro() ? ucwords( (string) wpforms_get_license_type() ) : 'Lite'; return 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) . '; WPForms/' . $license_type . '-' . WPFORMS_VERSION; } /** * Get the ISO 639-2 Language Code from user/site locale. * * @see http://www.loc.gov/standards/iso639-2/php/code_list.php * * @since 1.5.0 * * @return string */ function wpforms_get_language_code() { $default_lang = 'en'; $locale = get_user_locale(); if ( ! empty( $locale ) ) { $lang = explode( '_', $locale ); if ( ! empty( $lang ) && is_array( $lang ) ) { $default_lang = strtolower( $lang[0] ); } } return $default_lang; } /** * Changes array of items into string of items, separated by comma and sql-escaped. * * @see https://coderwall.com/p/zepnaw * * @since 1.7.4 * * @param mixed|array $items Item(s) to be joined into string. * @param string $format Can be %s or %d. * * @return string Items separated by comma and sql-escaped. */ function wpforms_wpdb_prepare_in( $items, $format = '%s' ) { global $wpdb; $items = (array) $items; $how_many = count( $items ); if ( $how_many === 0 ) { return ''; } $placeholders = array_fill( 0, $how_many, $format ); $prepared_format = implode( ',', $placeholders ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared return $wpdb->prepare( $prepared_format, $items ); } /** * Get the render engine slug according to the Modern Markup setting value and corresponding filter. * * @since 1.8.1 * * @return string */ function wpforms_get_render_engine() { $render_engine = empty( wpforms_setting( 'modern-markup', false ) ) ? 'classic' : 'modern'; /** * Filter current render engine slug. * Allows addons to use their own frontend rendering engine. * * @since 1.8.1 * * @param string $render_engine Render engine slug. */ $render_engine = apply_filters( 'wpforms_get_render_engine', $render_engine ); return $render_engine; }