예제 #1
0
 /**
  * Intercept EDD's [downloads] shortcode
  * @since 2.0.4
  */
 function edd_downloads_query($query)
 {
     if (!empty(FWP()->facet->query_args)) {
         $query = array_merge($query, FWP()->facet->query_args);
     }
     return $query;
 }
예제 #2
0
 /**
  * Initialize classes and WP hooks
  */
 function init()
 {
     // i18n
     $this->load_textdomain();
     // is_plugin_active
     include_once ABSPATH . 'wp-admin/includes/plugin.php';
     // classes
     foreach (array('helper', 'ajax', 'facet', 'indexer', 'display', 'upgrade') as $f) {
         include FACETWP_DIR . "/includes/class-{$f}.php";
     }
     new FacetWP_Upgrade();
     FWP()->helper = new FacetWP_Helper();
     FWP()->facet = new FacetWP_Facet();
     FWP()->indexer = new FacetWP_Indexer();
     FWP()->display = new FacetWP_Display();
     FWP()->ajax = new FacetWP_Ajax();
     // integrations
     foreach (array('searchwp', 'woocommerce', 'edd', 'acf') as $f) {
         include FACETWP_DIR . "/includes/integrations/{$f}/{$f}.php";
     }
     include FACETWP_DIR . '/includes/functions.php';
     // hooks
     add_action('admin_menu', array($this, 'admin_menu'));
     add_action('wp_enqueue_scripts', array($this, 'front_scripts'));
     add_action('admin_enqueue_scripts', array($this, 'admin_scripts'));
     add_filter('redirect_canonical', array($this, 'redirect_canonical'), 10, 2);
 }
예제 #3
0
 /**
  * Index each product's stock status
  * @since 2.1.4
  */
 function index_stock_status($return, $params)
 {
     $facet = $params['facet'];
     $defaults = $params['defaults'];
     if ('woocommerce/stock_status' == $facet['source']) {
         if ('product' == get_post_type($defaults['post_id'])) {
             WC()->api->includes();
             WC()->api->register_resources(new WC_API_Server('/'));
             $response = WC()->api->WC_API_Products->get_product($defaults['post_id']);
             $product = $response['product'];
             if ('variable' == $product['type']) {
                 $in_stock = false;
                 foreach ($product['variations'] as $variation) {
                     if (true === $variation['in_stock']) {
                         $in_stock = true;
                         break;
                     }
                 }
             } else {
                 $in_stock = $product['in_stock'];
             }
             $defaults['facet_value'] = (int) $in_stock;
             $defaults['facet_display_value'] = $in_stock ? __('In Stock', 'fwp') : __('Out of Stock', 'fwp');
             FWP()->indexer->index_row($defaults);
         }
         return true;
     }
     return $return;
 }
 public function term_link($link, $term, $taxonomy)
 {
     $facets = FWP()->helper->get_facets();
     $taxes = $sources = array();
     $permalink = FWP()->helper->get_setting('term_permalink', 'slug');
     $permalink_type = FWP()->helper->get_setting('permalink_type', 'get');
     $term = 'term_id' == $permalink ? $term->term_id : $term->slug;
     if (empty($facets)) {
         return $link;
     }
     foreach ($facets as $facet) {
         if (isset($facet['source'])) {
             $sources[$facet['name']] = $facet['source'];
         }
     }
     if (empty($sources)) {
         return $link;
     }
     foreach ($sources as $name => $source) {
         $source = str_replace('tax/', '', $source);
         if ($taxonomy == $source) {
             $post_type = get_post_type_archive_link('job_listing');
             if ('get' == $permalink_type) {
                 $url = add_query_arg('fwp_' . $name, $term, $post_type);
             } else {
                 $url = $post_type . '#!/' . $name . '=' . $term;
             }
             return esc_url($url);
         }
     }
     return $link;
 }
예제 #5
0
function listable_facetwp_archive_query($query_args)
{
    $uri = FWP()->facet->http_params['uri'];
    if (false !== strpos($uri, 'listing-category')) {
        $query_args['tax_query'][] = array('taxonomy' => 'job_listing_category', 'field' => 'slug', 'terms' => basename($uri));
    } elseif (false !== strpos($uri, 'listing-type')) {
        $query_args['tax_query'][] = array('taxonomy' => 'job_listing_type', 'field' => 'slug', 'terms' => basename($uri));
    } elseif (false !== strpos($uri, 'listing-region')) {
        $query_args['tax_query'][] = array('taxonomy' => 'job_listing_region', 'field' => 'slug', 'terms' => basename($uri));
    } elseif (false !== strpos($uri, 'listing-tag')) {
        $query_args['tax_query'][] = array('taxonomy' => 'job_listing_tag', 'field' => 'slug', 'terms' => basename($uri));
    }
    return $query_args;
}
예제 #6
0
 /**
  * Connect to the activation server to get update details
  */
 function check_update($transient)
 {
     if (empty($transient->checked)) {
         return $transient;
     }
     $request = wp_remote_post('http://api.facetwp.com', array('body' => array('action' => 'version', 'slug' => $this->slug, 'license' => $this->license, 'host' => FWP()->helper->get_http_host())));
     if (!is_wp_error($request) || 200 == wp_remote_retrieve_response_code($request)) {
         $response = unserialize($request['body']);
         if (!empty($response)) {
             if (version_compare($this->version, $response->version, '<')) {
                 $transient->response['facetwp/index.php'] = (object) array('slug' => $this->slug, 'plugin' => FACETWP_BASENAME, 'new_version' => $response->version, 'url' => $response->url, 'package' => $response->package);
             }
             update_option('facetwp_activation', json_encode($response->activation));
         }
     }
     return $transient;
 }
예제 #7
0
 /**
  * Handle "source_other" setting
  */
 function index_source_other($value, $params)
 {
     $facet = FWP()->helper->get_facet_by_name($params['facet_name']);
     if (!empty($facet['source_other'])) {
         $hierarchy = explode('/', substr($facet['source_other'], 4));
         $value = get_field($hierarchy[0], $params['post_id'], false);
         // handle repeater values
         if (1 < count($hierarchy)) {
             array_shift($hierarchy);
             $value = $this->process_field_value($value, $hierarchy);
             return reset($value);
             // return first element
         }
     }
     return $value;
 }
예제 #8
0
 public function get_facets($facets = false)
 {
     $facets = $facets ? $facets : listify_theme_mod('listing-archive-facetwp-defaults');
     $_facets = array();
     if (!is_array($facets)) {
         $facets = array_map('trim', explode(',', $facets));
     }
     foreach ($facets as $key => $facet_name) {
         $facet = FWP()->helper->get_facet_by_name($facet_name);
         if (!$facet) {
             continue;
         }
         $_facets[] = $facet;
     }
     return $_facets;
 }
예제 #9
0
    public $indexer;
    public $display;
    private static $instance;
    function __construct()
    {
        // setup variables
        define('FACETWP_VERSION', '2.2.8');
        define('FACETWP_DIR', dirname(__FILE__));
        define('FACETWP_URL', plugins_url(basename(FACETWP_DIR)));
        define('FACETWP_BASENAME', plugin_basename(__FILE__));
        // get the gears turning
        include FACETWP_DIR . '/includes/class-updater.php';
        include FACETWP_DIR . '/includes/class-init.php';
    }
    /**
     * Singleton
     */
    public static function instance()
    {
        if (!isset(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}
function FWP()
{
    return FacetWP::instance();
}
$facetwp = FWP();
예제 #10
0
 /**
  * Does a 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;
 }
예제 #11
0
 /**
  * Get ALL post IDs for the matching query
  * @return array An array of post IDs
  */
 function get_filtered_post_ids()
 {
     global $wpdb;
     // Only get relevant post IDs
     $args = array_merge($this->query_args, array('fields' => 'ids', 'posts_per_page' => -1, 'paged' => 1, 'cache_results' => false));
     $query = new WP_Query($args);
     $post_ids = (array) $query->posts;
     // Allow hooks to modify the default post IDs
     $post_ids = apply_filters('facetwp_pre_filtered_post_ids', $post_ids, $this);
     // Determine whether we need to store unfiltered post IDs
     $store_ids = apply_filters('facetwp_store_unfiltered_post_ids', false);
     if ($store_ids) {
         FWP()->unfiltered_post_ids = $post_ids;
     }
     foreach ($this->facets as $the_facet) {
         // Stop looping
         if (empty($post_ids)) {
             break;
         }
         $matches = array();
         $selected_values = $the_facet['selected_values'];
         if (empty($selected_values)) {
             continue;
         }
         // Get the facet details
         $facet_type = $the_facet['type'];
         // Handle each facet
         if (isset($this->facet_types[$facet_type]) && !empty($selected_values)) {
             $hook_params = array('facet' => $the_facet, 'selected_values' => $selected_values);
             // Hook to support custom filter_posts() handler
             $matches = apply_filters('facetwp_facet_filter_posts', false, $hook_params);
             if (false === $matches) {
                 $matches = $this->facet_types[$facet_type]->filter_posts($hook_params);
             }
         }
         // Skip this facet
         if ('continue' == $matches) {
             continue;
         }
         // Store post IDs per facet
         // Required for dropdowns and checkboxes in "or" mode
         if ($store_ids) {
             FWP()->or_values[$the_facet['name']] = $matches;
         }
         // Preserve post ID order for search facets
         if ('search' == $facet_type) {
             $this->is_search = true;
             $intersected_ids = array();
             foreach ($matches as $match) {
                 if (in_array($match, $post_ids)) {
                     $intersected_ids[] = $match;
                 }
             }
             $post_ids = $intersected_ids;
         } else {
             $post_ids = array_intersect($post_ids, $matches);
         }
     }
     // Return a zero array if no matches
     if (empty($post_ids)) {
         $post_ids = array(0);
     }
     // Reset any array keys
     $post_ids = array_values($post_ids);
     return apply_filters('facetwp_filtered_post_ids', $post_ids, $this);
 }
예제 #12
0
 /**
  * After the final list of post IDs has been produced,
  * sort them by distance if needed
  */
 function sort_by_distance($post_ids, $class)
 {
     $ordered_posts = FWP()->helper->facet_types['proximity']->ordered_posts;
     if (!empty($ordered_posts)) {
         // Sort the post IDs according to distance
         $intersected_ids = array();
         foreach ($ordered_posts as $p) {
             if (in_array($p, $post_ids)) {
                 $intersected_ids[] = $p;
             }
         }
         $post_ids = $intersected_ids;
     }
     return $post_ids;
 }
예제 #13
0
        $message .= ' (' . __('expires', 'fwp') . ' ' . date('M j, Y', strtotime($activation->expiration)) . ')';
    } else {
        $message = $activation->message;
    }
}
// Export feature
$export = array();
$settings = FWP()->helper->settings;
foreach ($settings['facets'] as $facet) {
    $export['facet-' . $facet['name']] = 'Facet - ' . $facet['label'];
}
foreach ($settings['templates'] as $template) {
    $export['template-' . $template['name']] = 'Template - ' . $template['label'];
}
// Data sources
$sources = FWP()->helper->get_data_sources();
?>

<script src="<?php 
echo FACETWP_URL;
?>
/assets/js/event-manager.js?ver=<?php 
echo FACETWP_VERSION;
?>
"></script>
<script src="<?php 
echo FACETWP_URL;
?>
/assets/js/src/query-builder.js?ver=<?php 
echo FACETWP_VERSION;
?>
예제 #14
0
 /**
  * Output facet scripts
  */
 function front_scripts()
 {
     // Not enqueued - front.js needs to load before front_scripts()
     if (true === apply_filters('facetwp_load_assets', $this->load_assets)) {
         if (true === apply_filters('facetwp_load_css', true)) {
             echo '<link href="' . FACETWP_URL . '/assets/css/front.css?ver=' . FACETWP_VERSION . '" rel="stylesheet">' . "\n";
         }
         echo '<script src="' . FACETWP_URL . '/assets/js/event-manager.js?ver=' . FACETWP_VERSION . '"></script>' . "\n";
         echo '<script src="' . FACETWP_URL . '/assets/js/front.js?ver=' . FACETWP_VERSION . '"></script>' . "\n";
         // Output the ajaxurl and HTTP params
         $this->ajaxurl();
         foreach ($this->active_types as $type) {
             FWP()->helper->facet_types[$type]->front_scripts();
         }
     }
 }
예제 #15
0
 /**
  * Generate the facet HTML
  */
 function render($params)
 {
     global $wpdb;
     $output = '';
     $facet = $params['facet'];
     $selected_values = (array) $params['selected_values'];
     $where_clause = $params['where_clause'];
     // Orderby
     $orderby = 'counter DESC, f.facet_display_value ASC';
     if ('display_value' == $facet['orderby']) {
         $orderby = 'f.facet_display_value ASC';
     } elseif ('raw_value' == $facet['orderby']) {
         $orderby = 'f.facet_value ASC';
     }
     // Visible results
     $num_visible = ctype_digit($facet['count']) ? $facet['count'] : 10;
     $max_depth = 0;
     $facet_parent_id = 0;
     // Determine the parent_id and depth
     if (!empty($selected_values[0])) {
         $value = $selected_values[0];
         $taxonomy = str_replace('tax/', '', $facet['source']);
         // Associate array of term IDs with term information
         $depths = FWP()->helper->get_term_depths($taxonomy);
         // Lookup the term ID from its slug
         $sql = "\n            SELECT t.term_id\n            FROM {$wpdb->terms} t\n            INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = t.term_id AND tt.taxonomy = %s\n            WHERE t.slug = %s\n            LIMIT 1";
         $facet_parent_id = (int) $wpdb->get_var($wpdb->prepare($sql, $taxonomy, $value));
         $max_depth = (int) $depths[$facet_parent_id]['depth'];
         $last_parent_id = $facet_parent_id;
         $prev_links = array();
         for ($i = 0; $i <= $max_depth; $i++) {
             $prev_links[] = array('value' => $depths[$last_parent_id]['slug'], 'label' => $depths[$last_parent_id]['name']);
             $last_parent_id = (int) $depths[$last_parent_id]['parent_id'];
         }
         $prev_links[] = array('value' => '', 'label' => __('Any', 'fwp'));
         // Reverse the navigation
         $prev_links = array_reverse($prev_links);
         $num_links = count($prev_links);
         foreach ($prev_links as $counter => $prev_link) {
             if ($counter == $num_links - 1) {
                 $active = ' checked';
             } else {
                 $active = '';
                 $prev_link['label'] = '&#8249; ' . $prev_link['label'];
             }
             if (0 < $counter) {
                 $output .= '<div class="facetwp-depth">';
             }
             $output .= '<div class="facetwp-link' . $active . '" data-value="' . $prev_link['value'] . '">' . $prev_link['label'] . '</div>';
         }
     }
     $sql = "\n        SELECT f.facet_value, f.facet_display_value, COUNT(*) AS counter\n        FROM {$wpdb->prefix}facetwp_index f\n        WHERE f.facet_name = '{$facet['name']}' {$where_clause} AND parent_id = '{$facet_parent_id}'\n        GROUP BY f.facet_value\n        ORDER BY {$orderby}";
     $results = $wpdb->get_results($sql);
     $key = 0;
     if (!empty($prev_links)) {
         $output .= '<div class="facetwp-depth">';
     }
     if (!empty($results)) {
         foreach ($results as $key => $result) {
             if ($key == (int) $num_visible) {
                 $output .= '<div class="facetwp-collapsed facetwp-hidden">';
             }
             $output .= '<div class="facetwp-link" data-value="' . $result->facet_value . '">';
             $output .= $result->facet_display_value . ' <span class="facetwp-counter">(' . $result->counter . ')</span>';
             $output .= '</div>';
         }
     }
     if ($num_visible <= $key) {
         $output .= '</div>';
         $output .= '<div class="facetwp-toggle">+ ' . __('More', 'fwp') . '</div>';
         $output .= '<div class="facetwp-toggle facetwp-hidden">- ' . __('Less', 'fwp') . '</div>';
     }
     for ($i = 0; $i <= $max_depth; $i++) {
         $output .= '</div>';
     }
     if (!empty($prev_links)) {
         $output .= '</div>';
     }
     return $output;
 }
예제 #16
0
    /**
     * Output any front-end scripts
     */
    function front_scripts()
    {
        FWP()->display->assets['flatpickr.css'] = FACETWP_URL . '/assets/js/flatpickr/flatpickr.css';
        FWP()->display->assets['flatpickr.js'] = FACETWP_URL . '/assets/js/flatpickr/flatpickr.min.js';
        ?>
<script>
(function($) {
    wp.hooks.addAction('facetwp/refresh/availability', function($this, facet_name) {
        var min = $this.find('.facetwp-date-min').val() || '';
        var max = $this.find('.facetwp-date-max').val() || '';
        var quantity = $this.find('.facetwp-quantity').val() || 1;
        FWP.facets[facet_name] = ('' != min && '' != max) ? [min, max, quantity] : [];
    });

    wp.hooks.addFilter('facetwp/selections/availability', function(output, params) {
        return params.selected_values[0] + ' - ' + params.selected_values[1];
    });

    $(document).on('facetwp-loaded', function() {
        var $dates = $('.facetwp-type-availability .facetwp-date:not(.ready)');
        if (0 === $dates.length) {
            return;
        }

        var flatpickr_opts = {
            //enableTime: true,
            minDate: new Date().toISOString().slice(0, 10),
            onReady: function(dateObj, dateStr, instance) {
                var $cal = $(instance.calendarContainer);
                if ($cal.find('.flatpickr-clear').length < 1) {
                    $cal.append('<div class="flatpickr-clear">Clear</div>');
                    $cal.find('.flatpickr-clear').on('click', function() {
                        instance.clear();
                        instance.close();
                    });
                }
            }
        };

        $dates.each(function() {
            var facet_name = $(this).closest('.facetwp-facet').attr('data-name');
            var opts = wp.hooks.applyFilters('facetwp/set_options/availability', flatpickr_opts, {
                'facet_name': facet_name
            });
            new Flatpickr(this, opts);
            $(this).addClass('ready');
        });
    });

    $(document).on('click', '.facetwp-availability-update', function() {
        FWP.autoload();
    });
})(jQuery);
</script>
<?php 
    }
예제 #17
0
 /**
  * License activation
  */
 function license()
 {
     $license = $_POST['license'];
     $request = wp_remote_post('http://api.facetwp.com', array('body' => array('action' => 'activate', 'slug' => 'facetwp', 'license' => $license, 'host' => FWP()->helper->get_http_host())));
     if (!is_wp_error($request) || 200 == wp_remote_retrieve_response_code($request)) {
         update_option('facetwp_license', $license);
         update_option('facetwp_activation', $request['body']);
         echo $request['body'];
     } else {
         echo json_encode(array('status' => 'error', 'message' => __('Error', 'fwp') . ': ' . $request->get_error_message()));
     }
     exit;
 }
예제 #18
0
/**
 * An alternate to using do_shortcode()
 * @since 1.7.5
 */
function facetwp_display()
{
    $args = func_get_args();
    $atts = isset($args[1]) ? array($args[0] => $args[1]) : array($args[0] => true);
    return FWP()->display->shortcode($atts);
}
예제 #19
0
 /**
  * Save a facet value to DB
  * This can be trigged by "facetwp_index_row" to handle multiple values
  * @since 1.2.5
  */
 function insert($params)
 {
     global $wpdb;
     // Only accept scalar values
     $value = $params['facet_value'];
     if ('' === $value || !is_scalar($value)) {
         return;
     }
     $wpdb->query($wpdb->prepare("INSERT INTO {$wpdb->prefix}facetwp_index\n            (post_id, facet_name, facet_source, facet_value, facet_display_value, term_id, parent_id, depth) VALUES (%d, %s, %s, %s, %s, %d, %d, %d)", $params['post_id'], $params['facet_name'], $params['facet_source'], FWP()->helper->safe_value($value), $params['facet_display_value'], $params['term_id'], $params['parent_id'], $params['depth']));
 }
예제 #20
0
 /**
  * Index a single value.
  *
  * @since 1.0.0
  *
  * @param array $value    The array of values to index. Available keys in the array are: post_id, facet_name,
  *                        facet_source, facet_value, facet_display_value, term_id, parent_id, and depth. For more
  *                        information, see @link https://facetwp.com/documentation/facetwp_index_row/
  * @param array $defaults Default values to use when indexing.
  */
 public function index_row($value, $defaults)
 {
     FWP()->indexer->index_row(wp_parse_args($value, $defaults));
 }
예제 #21
0
 /**
  * Store unfiltered post IDs if a dropdown facet exists
  */
 function store_unfiltered_post_ids($boolean)
 {
     if (FWP()->helper->facet_setting_exists('type', 'dropdown')) {
         return true;
     }
     return $boolean;
 }
예제 #22
0
 /**
  * Store unfiltered post IDs if a checkbox facet exists
  * with ghosts or "OR" mode enabled
  */
 function store_unfiltered_post_ids($boolean)
 {
     if (FWP()->helper->facet_setting_exists('ghosts', 'yes')) {
         return true;
     }
     if (FWP()->helper->facet_setting_exists('operator', 'or')) {
         return true;
     }
     return $boolean;
 }
예제 #23
0
 /**
  * Index the 2nd data source
  * @since 2.1.1
  */
 function index_row($params, $class)
 {
     if ($class->is_overridden) {
         return $params;
     }
     $facet = FWP()->helper->get_facet_by_name($params['facet_name']);
     if ('slider' == $facet['type'] && !empty($facet['source_other'])) {
         $other_params = $params;
         $other_params['facet_source'] = $facet['source_other'];
         $rows = $class->get_row_data($other_params);
         $params['facet_display_value'] = $rows[0]['facet_display_value'];
     }
     return $params;
 }