Merged in feature/plugins-update (pull request #9)
wp plugin updates from pantheon * wp plugin updates from pantheon
This commit is contained in:
600
wp/wp-content/plugins/facetwp/includes/class-helper.php
Normal file
600
wp/wp-content/plugins/facetwp/includes/class-helper.php
Normal file
@@ -0,0 +1,600 @@
|
||||
<?php
|
||||
|
||||
final class FacetWP_Helper
|
||||
{
|
||||
|
||||
/* (array) The facetwp_settings option (after hooks) */
|
||||
public $settings;
|
||||
|
||||
/* (array) Associative array of facet objects */
|
||||
public $facet_types;
|
||||
|
||||
/* (array) Cached data sources */
|
||||
public $data_sources;
|
||||
|
||||
/* (array) Cached terms */
|
||||
public $term_cache;
|
||||
|
||||
/* (array) Index table row counts */
|
||||
public $row_counts;
|
||||
|
||||
|
||||
function __construct() {
|
||||
$this->facet_types = $this->get_facet_types();
|
||||
$this->settings = $this->load_settings();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the URL hostname
|
||||
*/
|
||||
function get_http_host() {
|
||||
return parse_url( get_option( 'home' ), PHP_URL_HOST );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the current page URI
|
||||
*/
|
||||
function get_uri() {
|
||||
if ( isset( FWP()->facet->http_params ) ) {
|
||||
return FWP()->facet->http_params['uri'];
|
||||
}
|
||||
|
||||
$uri = parse_url( $_SERVER['REQUEST_URI'] );
|
||||
return isset( $uri['path'] ) ? trim( $uri['path'], '/' ) : '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get available facet types
|
||||
*/
|
||||
function get_facet_types() {
|
||||
if ( ! empty( $this->facet_types ) ) {
|
||||
return $this->facet_types;
|
||||
}
|
||||
|
||||
include( FACETWP_DIR . '/includes/facets/base.php' );
|
||||
|
||||
$types = [
|
||||
'checkboxes' => 'Facetwp_Facet_Checkboxes',
|
||||
'dropdown' => 'Facetwp_Facet_Dropdown',
|
||||
'radio' => 'Facetwp_Facet_Radio_Core',
|
||||
'fselect' => 'Facetwp_Facet_fSelect',
|
||||
'hierarchy' => 'Facetwp_Facet_Hierarchy',
|
||||
'slider' => 'Facetwp_Facet_Slider',
|
||||
'search' => 'Facetwp_Facet_Search',
|
||||
'autocomplete' => 'Facetwp_Facet_Autocomplete',
|
||||
'date_range' => 'Facetwp_Facet_Date_Range',
|
||||
'number_range' => 'Facetwp_Facet_Number_Range',
|
||||
'rating' => 'FacetWP_Facet_Rating',
|
||||
'proximity' => 'Facetwp_Facet_Proximity_Core',
|
||||
'pager' => 'FacetWP_Facet_Pager',
|
||||
'reset' => 'FacetWP_Facet_Reset',
|
||||
'sort' => 'FacetWP_Facet_Sort'
|
||||
];
|
||||
|
||||
$facet_types = [];
|
||||
|
||||
foreach ( $types as $slug => $class_name ) {
|
||||
include( FACETWP_DIR . "/includes/facets/$slug.php" );
|
||||
$facet_types[ $slug ] = new $class_name();
|
||||
}
|
||||
|
||||
return apply_filters( 'facetwp_facet_types', $facet_types );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get settings and allow for developer hooks
|
||||
*/
|
||||
function load_settings( $last_index = false ) {
|
||||
$name = $last_index ? 'facetwp_settings_last_index' : 'facetwp_settings';
|
||||
$option = get_option( $name );
|
||||
|
||||
$defaults = [
|
||||
'facets' => [],
|
||||
'templates' => [],
|
||||
'settings' => [
|
||||
'thousands_separator' => ',',
|
||||
'decimal_separator' => '.',
|
||||
'prefix' => '_',
|
||||
'load_jquery' => 'no'
|
||||
]
|
||||
];
|
||||
|
||||
$settings = ( false !== $option ) ? json_decode( $option, true ) : [];
|
||||
$settings = array_merge( $defaults, $settings );
|
||||
$settings['settings'] = array_merge( $defaults['settings'], $settings['settings'] );
|
||||
|
||||
// Store DB-based facet & template names
|
||||
$db_names = [];
|
||||
|
||||
foreach ( $settings['facets'] as $facet ) {
|
||||
$db_names[ 'facet-' . $facet['name'] ] = true;
|
||||
}
|
||||
|
||||
foreach ( $settings['templates'] as $template ) {
|
||||
$db_names[ 'template-' . $template['name'] ] = true;
|
||||
}
|
||||
|
||||
// Programmatically registered
|
||||
$facets = apply_filters( 'facetwp_facets', $settings['facets'] );
|
||||
$templates = apply_filters( 'facetwp_templates', $settings['templates'] );
|
||||
|
||||
$tmp_facets = [];
|
||||
$tmp_templates = [];
|
||||
|
||||
// Merge DB + code-based facets
|
||||
foreach ( $facets as $facet ) {
|
||||
$name = $facet['name'];
|
||||
$is_db_based = isset( $db_names[ "facet-$name" ] );
|
||||
|
||||
if ( ! $is_db_based ) {
|
||||
$facet['_code'] = true;
|
||||
}
|
||||
|
||||
if ( ! $is_db_based || empty( $tmp_facets[ $name ] ) ) {
|
||||
|
||||
// Valid facet type?
|
||||
if ( in_array( $facet['type'], array_keys( $this->facet_types ) ) ) {
|
||||
$tmp_facets[ $name ] = $facet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Merge DB + code-based templates
|
||||
foreach ( $templates as $template ) {
|
||||
$name = $template['name'];
|
||||
$is_db_based = isset( $db_names[ "template-$name" ] );
|
||||
|
||||
if ( ! $is_db_based ) {
|
||||
$template['_code'] = true;
|
||||
}
|
||||
|
||||
if ( ! $is_db_based || empty( $tmp_templates[ $name ] ) ) {
|
||||
$tmp_templates[ $name ] = $template;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert back to numerical arrays
|
||||
$settings['facets'] = array_values( $tmp_facets );
|
||||
$settings['templates'] = array_values( $tmp_templates );
|
||||
|
||||
// Filtered settings
|
||||
return $settings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a general setting value
|
||||
*
|
||||
* @param string $name The setting name
|
||||
* @param mixed $default The default value
|
||||
* @since 1.9
|
||||
*/
|
||||
function get_setting( $name, $default = '' ) {
|
||||
return $this->settings['settings'][ $name ] ?? $default;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an array of all facets
|
||||
* @return array
|
||||
*/
|
||||
function get_facets() {
|
||||
return $this->settings['facets'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an array of all templates
|
||||
* @return array
|
||||
*/
|
||||
function get_templates() {
|
||||
return $this->settings['templates'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all properties for a single facet
|
||||
* @param string $facet_name
|
||||
* @return mixed An array of facet info, or false
|
||||
*/
|
||||
function get_facet_by_name( $facet_name ) {
|
||||
foreach ( $this->get_facets() as $facet ) {
|
||||
if ( $facet_name == $facet['name'] ) {
|
||||
return $facet;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all properties for a single template
|
||||
*
|
||||
* @param string $template_name
|
||||
* @return mixed An array of template info, or false
|
||||
*/
|
||||
function get_template_by_name( $template_name ) {
|
||||
foreach ( $this->get_templates() as $template ) {
|
||||
if ( $template_name == $template['name'] ) {
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch facets using one of its settings
|
||||
* @param string $setting_name
|
||||
* @param mixed $setting_value
|
||||
* @return array
|
||||
*/
|
||||
function get_facets_by( $setting, $value ) {
|
||||
$matches = [];
|
||||
|
||||
foreach ( $this->get_facets() as $facet ) {
|
||||
if ( isset( $facet[ $setting ] ) && $value === $facet[ $setting ] ) {
|
||||
$matches[] = $facet;
|
||||
}
|
||||
}
|
||||
|
||||
return $matches;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get terms across all languages (thanks, WPML)
|
||||
* @since 3.8.5
|
||||
*/
|
||||
function get_terms( $taxonomy ) {
|
||||
global $wpdb;
|
||||
|
||||
$sql = "
|
||||
SELECT t.term_id, t.name, t.slug, tt.parent FROM {$wpdb->term_taxonomy} tt
|
||||
INNER JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
|
||||
WHERE tt.taxonomy = %s";
|
||||
|
||||
return $wpdb->get_results( $wpdb->prepare( $sql, $taxonomy ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an array of term information, including depth
|
||||
* @param string $taxonomy The taxonomy name
|
||||
* @return array Term information
|
||||
* @since 0.9.0
|
||||
*/
|
||||
function get_term_depths( $taxonomy ) {
|
||||
|
||||
if ( isset( $this->term_cache[ $taxonomy ] ) ) {
|
||||
return $this->term_cache[ $taxonomy ];
|
||||
}
|
||||
|
||||
$output = [];
|
||||
$parents = [];
|
||||
|
||||
$terms = $this->get_terms( $taxonomy );
|
||||
|
||||
// Get term parents
|
||||
foreach ( $terms as $term ) {
|
||||
$parents[ $term->term_id ] = $term->parent;
|
||||
}
|
||||
|
||||
// Build the term array
|
||||
foreach ( $terms as $term ) {
|
||||
$output[ $term->term_id ] = [
|
||||
'term_id' => $term->term_id,
|
||||
'name' => $term->name,
|
||||
'slug' => $term->slug,
|
||||
'parent_id' => $term->parent,
|
||||
'depth' => 0
|
||||
];
|
||||
|
||||
$current_parent = $term->parent;
|
||||
while ( 0 < (int) $current_parent ) {
|
||||
$current_parent = $parents[ $current_parent ];
|
||||
$output[ $term->term_id ]['depth']++;
|
||||
|
||||
// Prevent an infinite loop
|
||||
if ( 50 < $output[ $term->term_id ]['depth'] ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->term_cache[ $taxonomy ] = $output;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finish sorting the facet values
|
||||
* The results are already sorted by depth and (name OR count), we just need
|
||||
* to move the children directly below their parents
|
||||
*/
|
||||
function sort_taxonomy_values( $values = [], $orderby = 'count' ) {
|
||||
$final = [];
|
||||
$cache = [];
|
||||
|
||||
// Create an "order" sort value based on the top-level items
|
||||
foreach ( $values as $key => $val ) {
|
||||
if ( 0 == $val['depth'] ) {
|
||||
$val['order'] = $key;
|
||||
$cache[ $val['term_id'] ] = $key;
|
||||
$final[] = $val;
|
||||
}
|
||||
elseif ( isset( $cache[ $val['parent_id'] ] ) ) { // skip orphans
|
||||
$val['order'] = $cache[ $val['parent_id'] ] . ".$key"; // dot-separated hierarchy string
|
||||
$cache[ $val['term_id'] ] = $val['order'];
|
||||
$final[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the array based on the new "order" element
|
||||
// Since this is a dot-separated hierarchy string, use version_compare
|
||||
usort( $final, function( $a, $b ) {
|
||||
return version_compare( $a['order'], $b['order'] );
|
||||
});
|
||||
|
||||
return $final;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sanitize SQL data
|
||||
* @return mixed The sanitized value(s)
|
||||
* @since 3.0.7
|
||||
*/
|
||||
function sanitize( $input ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_array( $input ) ) {
|
||||
$output = [];
|
||||
|
||||
foreach ( $input as $key => $val ) {
|
||||
$output[ $key ] = $this->sanitize( $val );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( $wpdb->dbh && $wpdb->use_mysqli ) {
|
||||
$output = mysqli_real_escape_string( $wpdb->dbh, $input );
|
||||
}
|
||||
else {
|
||||
$output = addslashes( $input );
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Does an active facet with the specified setting exist?
|
||||
* @return boolean
|
||||
* @since 1.4.0
|
||||
*/
|
||||
function facet_setting_exists( $setting_name, $setting_value ) {
|
||||
foreach ( FWP()->facet->facets as $f ) {
|
||||
if ( isset( $f[ $setting_name ] ) && $f[ $setting_name ] == $setting_value ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Does this facet have a setting with the specified value?
|
||||
* @return boolean
|
||||
* @since 2.3.4
|
||||
*/
|
||||
function facet_is( $facet, $setting_name, $setting_value ) {
|
||||
if ( is_string( $facet ) ) {
|
||||
$facet = $this->get_facet_by_name( $facet );
|
||||
}
|
||||
|
||||
if ( isset( $facet[ $setting_name ] ) && $facet[ $setting_name ] == $setting_value ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Hash a facet value if needed
|
||||
* @return string
|
||||
* @since 2.1
|
||||
*/
|
||||
function safe_value( $value ) {
|
||||
$value = remove_accents( $value );
|
||||
|
||||
if ( preg_match( '/[^a-z0-9_.\- ]/i', $value ) ) {
|
||||
if ( ! preg_match( '/^\d{4}-(0[1-9]|1[012])-([012]\d|3[01])/', $value ) ) {
|
||||
$value = md5( $value );
|
||||
}
|
||||
}
|
||||
|
||||
$value = str_replace( ' ', '-', strtolower( $value ) );
|
||||
$value = preg_replace( '/[-]{2,}/', '-', $value );
|
||||
$value = ( 50 < strlen( $value ) ) ? substr( $value, 0, 50 ) : $value;
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Properly format numbers, taking separators into account
|
||||
* @return number
|
||||
* @since 2.7.5
|
||||
*/
|
||||
function format_number( $num ) {
|
||||
$sep_decimal = $this->get_setting( 'decimal_separator' );
|
||||
$sep_thousands = $this->get_setting( 'thousands_separator' );
|
||||
|
||||
$num = str_replace( $sep_thousands, '', $num );
|
||||
$num = ( ',' == $sep_decimal ) ? str_replace( ',', '.', $num ) : $num;
|
||||
$num = preg_replace( '/[^0-9-.]/', '', $num );
|
||||
|
||||
return $num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get facet data sources
|
||||
* @return array
|
||||
* @since 2.2.1
|
||||
*/
|
||||
function get_data_sources( $context = 'default' ) {
|
||||
global $wpdb;
|
||||
|
||||
// Cached?
|
||||
if ( ! empty( $this->data_sources ) ) {
|
||||
$sources = $this->data_sources;
|
||||
}
|
||||
else {
|
||||
|
||||
// Get excluded meta keys
|
||||
$excluded_fields = apply_filters( 'facetwp_excluded_custom_fields', [
|
||||
'_edit_last',
|
||||
'_edit_lock',
|
||||
] );
|
||||
|
||||
// Get taxonomies
|
||||
$taxonomies = get_taxonomies( [], 'object' );
|
||||
|
||||
// Get custom fields
|
||||
$meta_keys = $wpdb->get_col( "SELECT DISTINCT meta_key FROM {$wpdb->postmeta} ORDER BY meta_key" );
|
||||
$custom_fields = array_diff( $meta_keys, $excluded_fields );
|
||||
|
||||
$sources = [
|
||||
'posts' => [
|
||||
'label' => __( 'Posts', 'fwp' ),
|
||||
'choices' => [
|
||||
'post_type' => __( 'Post Type', 'fwp' ),
|
||||
'post_date' => __( 'Post Date', 'fwp' ),
|
||||
'post_modified' => __( 'Post Modified', 'fwp' ),
|
||||
'post_title' => __( 'Post Title', 'fwp' ),
|
||||
'post_author' => __( 'Post Author', 'fwp' )
|
||||
],
|
||||
'weight' => 10
|
||||
],
|
||||
'taxonomies' => [
|
||||
'label' => __( 'Taxonomies', 'fwp' ),
|
||||
'choices' => [],
|
||||
'weight' => 20
|
||||
],
|
||||
'custom_fields' => [
|
||||
'label' => __( 'Custom Fields', 'fwp' ),
|
||||
'choices' => [],
|
||||
'weight' => 30
|
||||
]
|
||||
];
|
||||
|
||||
foreach ( $taxonomies as $tax ) {
|
||||
$sources['taxonomies']['choices'][ 'tax/' . $tax->name ] = $tax->labels->name . ' (' . $tax->name . ')';
|
||||
}
|
||||
|
||||
foreach ( $custom_fields as $cf ) {
|
||||
if ( 0 !== strpos( $cf, '_oembed_' ) ) {
|
||||
$sources['custom_fields']['choices'][ 'cf/' . $cf ] = $cf;
|
||||
}
|
||||
}
|
||||
|
||||
$this->data_sources = $sources;
|
||||
}
|
||||
|
||||
$sources = apply_filters( 'facetwp_facet_sources', $sources, $context );
|
||||
|
||||
uasort( $sources, [ $this, 'sort_by_weight' ] );
|
||||
|
||||
return $sources;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort facetwp_facet_sources by weight
|
||||
* @since 2.7.5
|
||||
*/
|
||||
function sort_by_weight( $a, $b ) {
|
||||
$a['weight'] = $a['weight'] ?? 10;
|
||||
$b['weight'] = $b['weight'] ?? 10;
|
||||
|
||||
if ( $a['weight'] == $b['weight'] ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ( $a['weight'] < $b['weight'] ) ? -1 : 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get row counts for all facets
|
||||
* @since 3.3.4
|
||||
*/
|
||||
function get_row_counts() {
|
||||
if ( isset( $this->row_counts ) ) {
|
||||
return $this->row_counts;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$output = [];
|
||||
$results = $wpdb->get_results( "SELECT facet_name, COUNT(*) AS row_count FROM {$wpdb->prefix}facetwp_index GROUP BY facet_name" );
|
||||
|
||||
foreach ( $results as $result ) {
|
||||
$output[ $result->facet_name ] = (int) $result->row_count;
|
||||
}
|
||||
|
||||
$this->row_counts = $output;
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Grab the license key
|
||||
* @since 3.0.3
|
||||
*/
|
||||
function get_license_key() {
|
||||
$license_key = defined( 'FACETWP_LICENSE_KEY' ) ? FACETWP_LICENSE_KEY : get_option( 'facetwp_license' );
|
||||
$license_key = apply_filters( 'facetwp_license_key', $license_key );
|
||||
return sanitize_key( trim( $license_key ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the license is active
|
||||
* @since 3.3.0
|
||||
*/
|
||||
function is_license_active() {
|
||||
return ( 'success' == $this->get_license_meta( 'status' ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a license meta value
|
||||
* Possible keys: status, message, expiration, payment_id, price_id
|
||||
* @since 3.5.3
|
||||
*/
|
||||
function get_license_meta( $key = 'status' ) {
|
||||
$activation = get_option( 'facetwp_activation' );
|
||||
|
||||
if ( ! empty( $activation ) ) {
|
||||
$data = json_decode( $activation, true );
|
||||
|
||||
if ( isset( $data[ $key ] ) ) {
|
||||
return $data[ $key ];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user