/** * Singleton instance * * @return GravityView_Plugin GravityView_Plugin object */ public static function getInstance() { if (empty(self::$instance)) { self::$instance = new self(); } return self::$instance; }
/** * Singleton instance * * @return GravityView_Plugin GravityView_Plugin object */ public static function getInstance() { if (empty(self::$theInstance)) { self::$theInstance = new GravityView_Plugin(); } return self::$theInstance; }
/** * Wrapper function to make sure GravityView_Extension has loaded * @return void */ function gv_extension_featured_entry_load() { if (!class_exists('GravityView_Extension')) { if (class_exists('GravityView_Plugin') && is_callable(array('GravityView_Plugin', 'include_extension_framework'))) { GravityView_Plugin::include_extension_framework(); } else { // We prefer to use the one bundled with GravityView, but if it doesn't exist, go here. include_once GV_DT_DIR . 'lib/class-gravityview-extension.php'; } } class GV_Extension_DataTables extends GravityView_Extension { protected $_title = 'DataTables'; protected $_version = '1.3'; const version = '1.3'; protected $_text_domain = 'gv-datatables'; protected $_min_gravityview_version = '1.1.7'; protected $_path = __FILE__; public function add_hooks() { // load DataTables admin logic add_action('gravityview_include_backend_actions', array($this, 'backend_actions')); // load DataTables core logic add_action('init', array($this, 'core_actions'), 19); // Register specific template. Run at 30 priority because GravityView_Plugin::frontend_actions() runs at 20 add_action('init', array($this, 'register_templates'), 30); } function backend_actions() { include_once GV_DT_DIR . 'includes/class-admin-datatables.php'; } function core_actions() { include_once GV_DT_DIR . 'includes/class-datatables-data.php'; include_once GV_DT_DIR . 'includes/extensions/class-datatables-extension.php'; include_once GV_DT_DIR . 'includes/extensions/class-datatables-tabletools.php'; include_once GV_DT_DIR . 'includes/extensions/class-datatables-scroller.php'; include_once GV_DT_DIR . 'includes/extensions/class-datatables-fixedheader.php'; include_once GV_DT_DIR . 'includes/extensions/class-datatables-responsive.php'; } function register_templates() { include_once GV_DT_DIR . 'includes/class-datatables-template.php'; } } new GV_Extension_DataTables(); }
/** * Read the $post and process the View data inside * @param array $wp Passed in the `wp` hook. Not used. * @return void */ function parse_content($wp = array()) { global $post; // If in admin and NOT AJAX request, get outta here. if (GravityView_Plugin::is_admin()) { return; } // Calculate requested Views $this->setGvOutputData(GravityView_View_Data::getInstance($post)); // !important: we need to run this before getting single entry (to kick the advanced filter) $this->set_context_view_id(); $this->setIsGravityviewPostType(get_post_type($post) === 'gravityview'); $post_id = $this->getPostId() ? $this->getPostId() : (isset($post) ? $post->ID : null); $this->setPostId($post_id); $post_has_shortcode = !empty($post->post_content) ? gravityview_has_shortcode_r($post->post_content, 'gravityview') : false; $this->setPostHasShortcode($this->isGravityviewPostType() ? null : !empty($post_has_shortcode)); // check if the View is showing search results (only for multiple entries View) $this->setIsSearch($this->is_searching()); unset($entry, $post_id, $post_has_shortcode); }
/** * * @param $view_id */ public function render_widget_hooks($view_id) { if (empty($view_id) || 'single' == gravityview_get_context()) { return; } $view_data = gravityview_get_current_view_data($view_id); // TODO: Move to sep. method, use an action instead wp_enqueue_style('gravityview_default_style'); // get View widget configuration $widgets = $view_data['widgets']; $rows = GravityView_Plugin::get_default_widget_areas(); switch (current_filter()) { case 'gravityview_before': $zone = 'header'; break; case 'gravityview_after': $zone = 'footer'; break; } // Prevent being called twice if (did_action($zone . '_' . $view_id . '_widgets')) { return; } // TODO Convert to partials ?> <div class="gv-grid"> <?php foreach ($rows as $row) { foreach ($row as $col => $areas) { $column = $col == '2-2' ? '1-2 gv-right' : $col . ' gv-left'; ?> <div class="gv-grid-col-<?php echo esc_attr($column); ?> "> <?php if (!empty($areas)) { foreach ($areas as $area) { if (!empty($widgets[$zone . '_' . $area['areaid']])) { foreach ($widgets[$zone . '_' . $area['areaid']] as $widget) { do_action("gravityview_render_widget_{$widget['id']}", $widget); } } } } ?> </div> <?php } // $row ?> <?php } // $rows ?> </div> <?php // Prevent being called twice do_action($zone . '_' . $view_id . '_widgets'); }
/** * Add Settings link to GravityView menu * @return void */ public function create_app_menu() { /** * If not multisite, always show. * If multisite and the plugin is network activated, show; we need to register the submenu page for the Network Admin settings to work. * If multisite and not network admin, we don't want the settings to show. * @since 1.7.6 */ $show_submenu = !is_multisite() || is_main_site() || !GravityView_Plugin::is_network_activated() || is_network_admin() && GravityView_Plugin::is_network_activated(); /** * Override whether to show the Settings menu on a per-blog basis. * @since 1.7.6 * @param bool $hide_if_network_activated Default: true */ $show_submenu = apply_filters('gravityview/show-settings-menu', $show_submenu); if ($show_submenu) { add_submenu_page('edit.php?post_type=gravityview', __('Settings', 'gravityview'), __('Settings', 'gravityview'), $this->_capabilities_app_settings, $this->_slug . '_settings', array($this, 'app_tab_page')); } }
/** * Fill in active areas with preset configuration according to the template selected * @return void */ function get_preset_fields_config() { $this->check_ajax_nonce(); if (empty($_POST['template_id'])) { exit(false); } // get the fields xml config file for this specific preset $preset_fields_path = apply_filters('gravityview_template_fieldsxml', array(), $_POST['template_id']); // import fields if (!empty($preset_fields_path)) { $presets = $this->import_fields($preset_fields_path); } else { $presets = array('widgets' => array(), 'fields' => array()); } $template_id = esc_attr($_POST['template_id']); // template areas $template_areas_directory = apply_filters('gravityview_template_active_areas', array(), $template_id, 'directory'); $template_areas_single = apply_filters('gravityview_template_active_areas', array(), $template_id, 'single'); // widget areas $default_widget_areas = GravityView_Plugin::get_default_widget_areas(); ob_start(); do_action('gravityview_render_active_areas', $template_id, 'widget', 'header', $default_widget_areas, $presets['widgets']); $response['header'] = ob_get_clean(); ob_start(); do_action('gravityview_render_active_areas', $template_id, 'widget', 'footer', $default_widget_areas, $presets['widgets']); $response['footer'] = ob_get_clean(); ob_start(); do_action('gravityview_render_active_areas', $template_id, 'field', 'directory', $template_areas_directory, $presets['fields']); $response['directory'] = ob_get_clean(); ob_start(); do_action('gravityview_render_active_areas', $template_id, 'field', 'single', $template_areas_single, $presets['fields']); $response['single'] = ob_get_clean(); $response = array_map('gravityview_strip_whitespace', $response); do_action('gravityview_log_debug', '[get_preset_fields_config] AJAX Response', $response); exit(json_encode($response)); }
/** * Wrapper function to make sure GravityView_Extension has loaded * @return void */ function gv_extension_visual_composer_load() { if (!class_exists('GravityView_Extension')) { if (class_exists('GravityView_Plugin') && is_callable(array('GravityView_Plugin', 'include_extension_framework'))) { GravityView_Plugin::include_extension_framework(); } else { // We prefer to use the one bundled with GravityView, but if it doesn't exist, go here. include_once plugin_dir_path(__FILE__) . 'lib/class-gravityview-extension.php'; } } class GravityView_Visual_Composer extends GravityView_Extension { protected $_title = 'Visual Composer'; protected $_version = '1.0.3'; protected $_min_gravityview_version = '1.1.7'; protected $_text_domain = 'gravityview-visual-composer'; protected $_path = __FILE__; function add_hooks() { // Visual Composer isn't loaded. if (!function_exists('vc_map')) { self::add_notice(array('message' => sprintf('The GravityView Visual Composer extension requires the %sVisual Composer%s plugin.', '<a href="http://katz.si/visualcomposer">', '</a>'))); do_action('gravityview_log_debug', 'GravityView_Visual_Composer[add_hooks] Not loading: Visual Composer isnt active.'); return; } add_action('admin_init', array($this, 'vc_map')); } /** * Add the GravityView menu to the Visual Composer menu * @uses vc_map * @return void */ function vc_map() { global $vc_manager; $views = get_posts(array('post_type' => 'gravityview', 'numberposts' => -1, 'status' => 'publish')); if (empty($views) || is_wp_error($views)) { // By default, there are no Views found. $gravityview_array[__('No GravityView Views found.', 'gravityview-visual-composer')] = ''; $params = array(array('type' => 'dropdown', 'heading' => __('View', 'gravityview-visual-composer'), 'param_name' => 'id', 'value' => $gravityview_array, 'description' => GravityView_Post_Types::no_views_text(), 'admin_label' => true)); } else { // Overwrite the default $views_array = array(__('Select a View to Insert', 'gravityview-visual-composer') => ''); // Map the title of the view to the ID foreach ($views as $view) { $title = !empty($view->post_title) ? esc_attr($view->post_title) : __('(no title)', 'gravityview-visual-composer'); $views_array[$title] = $view->ID; } $params = $this->get_params($views_array); } vc_map(array('name' => __('GravityView', 'gravityview-visual-composer'), 'base' => 'gravityview', 'icon' => plugins_url('assets/img/icon.png', __FILE__), 'category' => __('Content', 'gravityview-visual-composer'), 'description' => __('Embed a View', 'gravityview-visual-composer'), 'params' => $params)); } // if gravityview active /** * Map GravityView * @see GravityView_View_Data::get_default_args() * @param array $views Array of Views * @return array Array of parameters */ function get_params($views_array) { if (!class_exists('GravityView_View_Data')) { return $views_array; } $default_params = array('page_size' => GravityView_View_Data::get_default_arg('page_size', true), 'show_only_approved' => GravityView_View_Data::get_default_arg('show_only_approved', true), 'lightbox' => GravityView_View_Data::get_default_arg('lightbox', true)); // Add the view picker first $params = array(array('value' => $views_array, 'heading' => __('View', 'gravityview-visual-composer'), 'description' => __('Select a View to add it to your post or page.', 'gravityview-visual-composer'), 'type' => 'dropdown', 'param_name' => 'id', 'admin_label' => true)); foreach (array('page_size', 'lightbox', 'show_only_approved', 'user_edit') as $key) { $param = GravityView_View_Data::get_default_arg($key, true); $type = isset($param['type']) ? $param['type'] : null; $heading = isset($param['label']) ? $param['label'] : null; $value = isset($param['value']) ? $param['value'] : null; // Different name for dropdown switch ($param['type']) { case 'select': $type = 'dropdown'; $value = isset($param['options']) ? $param['options'] : array(); break; case 'checkbox': $heading = ''; $value = array($heading => $value); break; case 'number': case 'text': $type = 'textfield'; break; } $params[] = array('type' => $type, 'heading' => $heading, 'class' => !empty($param['class']) ? $param['class'] : NULL, 'param_name' => $key, 'description' => empty($param['desc']) ? NULL : $param['desc'], 'value' => $value, 'admin_label' => true); } return $params; } } new GravityView_Visual_Composer(); }
/** * main AJAX logic to retrieve DataTables data */ function get_datatables_data() { global $gravityview_view; if (empty($_POST)) { return; } // Prevent error output ob_start(); // Send correct headers $this->do_ajax_headers('application/javascript'); $this->check_ajax_nonce(); if (empty($_POST['view_id'])) { do_action('gravityview_log_debug', '[DataTables] AJAX request - View ID check failed'); exit(false); } // Prevent emails from being encrypted add_filter('gravityview_email_prevent_encrypt', '__return_true'); do_action('gravityview_log_debug', '[DataTables] AJAX Request ($_POST)', $_POST); // include some frontend logic if (class_exists('GravityView_Plugin') && !class_exists('GravityView_View')) { GravityView_Plugin::getInstance()->frontend_actions(); } // Pass $_GET variables to the View functions, since they're relied on heavily // for searching and filtering, for example the A-Z widget $_GET = json_decode(stripslashes($_POST['getData']), true); $view_id = intval($_POST['view_id']); // create the view object based on the post_id $GravityView_View_Data = GravityView_View_Data::getInstance((int) $_POST['post_id']); // get the view data $view_data = $GravityView_View_Data->get_view($view_id); $view_data['atts']['id'] = $view_id; $atts = $view_data['atts']; // check for order/sorting if (isset($_POST['order'][0]['column'])) { $order_index = $_POST['order'][0]['column']; if (!empty($_POST['columns'][$order_index]['name'])) { // remove prefix 'gv_' $atts['sort_field'] = substr($_POST['columns'][$order_index]['name'], 3); $atts['sort_direction'] = !empty($_POST['order'][0]['dir']) ? strtoupper($_POST['order'][0]['dir']) : 'ASC'; } } // check for search if (!empty($_POST['search']['value'])) { $atts['search_value'] = esc_attr(stripslashes_deep($_POST['search']['value'])); } // Paging/offset $atts['page_size'] = isset($_POST['length']) ? intval($_POST['length']) : ''; $atts['offset'] = isset($_POST['start']) ? intval($_POST['start']) : 0; // prepare to get entries $atts = wp_parse_args($atts, GravityView_View_Data::get_default_args()); // check if someone requested the full filtered data (eg. TableTools print button) if ($atts['page_size'] == '-1') { $mode = 'all'; $atts['page_size'] = PHP_INT_MAX; } else { // regular mode - get view entries $mode = 'page'; } $view_data['atts'] = $atts; $gravityview_view = new GravityView_View($view_data); if (class_exists('GravityView_Cache')) { // We need to fetch the search criteria and pass it to the Cache so that the search is used when generating the cache transient key. $search_criteria = GravityView_frontend::get_search_criteria($atts, $view_data['form_id']); // make sure to allow late filter ( used on Advanced Filter extension ) $criteria = apply_filters('gravityview_search_criteria', array('search_criteria' => $search_criteria), $view_data['form_id'], $_POST['view_id']); $atts['search_criteria'] = $criteria['search_criteria']; // Cache key should also depend on the View assigned fields $atts['directory_table-columns'] = !empty($view_data['fields']['directory_table-columns']) ? $view_data['fields']['directory_table-columns'] : array(); // cache depends on user session $atts['user_session'] = $this->get_user_session(); $Cache = new GravityView_Cache($view_data['form_id'], $atts); if ($output = $Cache->get()) { do_action('gravityview_log_debug', '[DataTables] Cached output found; using cache with key ' . $Cache->get_key()); // update DRAW (mr DataTables is very sensitive!) $temp = json_decode($output, true); $temp['draw'] = intval($_POST['draw']); $output = json_encode($temp); exit($output); } } $view_entries = GravityView_frontend::get_view_entries($atts, $view_data['form_id']); $data = $this->get_output_data($view_entries, $view_data); // wrap all $output = array('draw' => intval($_POST['draw']), 'recordsTotal' => intval($view_entries['count']), 'recordsFiltered' => intval($view_entries['count']), 'data' => $data); do_action('gravityview_log_debug', '[DataTables] Ajax request answer', $output); $json = json_encode($output); if (class_exists('GravityView_Cache')) { do_action('gravityview_log_debug', '[DataTables] Setting cache'); // Cache results $Cache->set($json, 'datatables_output'); } // End prevent error output ob_end_clean(); exit($json); }
/** * Render the widget active areas * @param string $zone Either 'header' or 'footer' * @param string $post_id Current Post ID (view) * @return string html */ function render_widgets_active_areas($template_id = '', $zone, $post_id = '') { $default_widget_areas = GravityView_Plugin::get_default_widget_areas(); $widgets = array(); if (!empty($post_id)) { $widgets = get_post_meta($post_id, '_gravityview_directory_widgets', true); } ob_start(); ?> <div class="gv-grid gv-grid-pad gv-grid-border" id="directory-<?php echo $zone; ?> -widgets"> <?php $this->render_active_areas($template_id, 'widget', $zone, $default_widget_areas, $widgets); ?> </div> <?php $output = ob_get_clean(); echo $output; return $output; }
/** * Setup all Gravity View's files * * @since 1.9 */ public function install() { $GV = GravityView_Plugin::getInstance(); $GV->frontend_actions(); }
/** * Register the updater for the Extension using GravityView license information * * @return void */ public function settings() { // If doing ajax, get outta here if (false === GravityView_Plugin::is_admin()) { return; } if (!class_exists('EDD_SL_Plugin_Updater')) { include_once plugin_dir_path(__FILE__) . 'lib/EDD_SL_Plugin_Updater.php'; } $license = $this->get_license(); // Don't update if invalid license. if (false === $license || empty($license['status']) || strtolower($license['status']) !== 'valid') { return; } new EDD_SL_Plugin_Updater($this->_remote_update_url, $this->_path, array('version' => $this->_version, 'license' => $license['license'], 'item_name' => $this->_title, 'author' => strip_tags($this->_author))); }
/** * * @param $view_id */ public function render_widget_hooks($view_id) { if (empty($view_id) || 'single' == gravityview_get_context()) { do_action('gravityview_log_debug', __METHOD__ . ' - Not rendering widgets; single entry'); return; } $view_data = gravityview_get_current_view_data($view_id); // TODO: Move to sep. method, use an action instead wp_enqueue_style('gravityview_default_style'); // get View widget configuration $widgets = $view_data['widgets']; $rows = GravityView_Plugin::get_default_widget_areas(); switch (current_filter()) { case 'gravityview_before': $zone = 'header'; break; case 'gravityview_after': $zone = 'footer'; break; } // Prevent being called twice if (did_action($zone . '_' . $view_id . '_widgets')) { do_action('gravityview_log_debug', sprintf('%s - Not rendering %s; already rendered', __METHOD__, $zone . '_' . $view_id . '_widgets')); return; } // TODO Convert to partials ?> <div class="gv-grid"> <?php foreach ($rows as $row) { foreach ($row as $col => $areas) { $column = $col == '2-2' ? '1-2 gv-right' : $col . ' gv-left'; ?> <div class="gv-grid-col-<?php echo esc_attr($column); ?> "> <?php if (!empty($areas)) { foreach ($areas as $area) { if (!empty($widgets[$zone . '_' . $area['areaid']])) { foreach ($widgets[$zone . '_' . $area['areaid']] as $widget) { do_action("gravityview_render_widget_{$widget['id']}", $widget); } } } } ?> </div> <?php } // $row ?> <?php } // $rows ?> </div> <?php /** * Prevent widgets from being called twice. * Checking for loop_start prevents themes and plugins that pre-process shortcodes from triggering the action before displaying. Like, ahem, the Divi theme and WordPress SEO plugin */ if (did_action('loop_start')) { do_action($zone . '_' . $view_id . '_widgets'); } }
/** * Add $this->shortcode_name shortcode to output self::render_frontend() */ function add_shortcode($run_on_singular = true) { global $post; if (GravityView_Plugin::is_admin()) { return; } if (empty($this->shortcode_name)) { return; } // If the widget shouldn't output on single entries, don't show it if (empty($this->show_on_single) && class_exists('GravityView_frontend') && GravityView_frontend::is_single_entry()) { do_action('gravityview_log_debug', sprintf('%s[add_shortcode]: Skipping; set to not run on single entry.', get_class($this))); add_shortcode($this->shortcode_name, '__return_null'); return; } if (!has_gravityview_shortcode($post)) { do_action('gravityview_log_debug', sprintf('%s[add_shortcode]: No shortcode present; not adding render_frontend shortcode.', get_class($this))); add_shortcode($this->shortcode_name, '__return_null'); return; } add_shortcode($this->shortcode_name, array($this, 'render_shortcode')); }
/** * Outputs the admin notices generated by the plugin * * @return void */ public function admin_notice() { if (empty(self::$admin_notices)) { return; } if (GravityView_Plugin::is_network_activated() && !is_main_site()) { return; } //don't display a message if use has dismissed the message for this version self::$dismissed_notices = (array) get_transient('gravityview_dismissed_notices'); foreach (self::$admin_notices as $notice) { if (false === $this->_maybe_show_notice($notice)) { continue; } echo '<div id="message" class="' . esc_attr($notice['class']) . '">'; // Too cute to leave out. echo GravityView_Admin::get_floaty(); if (!empty($notice['title'])) { echo '<h3>' . esc_html($notice['title']) . '</h3>'; } echo wpautop($notice['message']); if (!empty($notice['dismiss'])) { $dismiss = esc_attr($notice['dismiss']); $url = esc_url(add_query_arg(array('gv-dismiss' => wp_create_nonce('dismiss'), 'notice' => $dismiss))); echo wpautop('<a href="' . $url . '" data-notice="' . $dismiss . '" class="button-small button button-secondary">' . esc_html__('Dismiss', 'gravityview') . '</a>'); } echo '<div class="clear"></div>'; echo '</div>'; } //reset the notices handler self::$admin_notices = array(); }
/** * Generate a link to an entry. The link can be an edit, delete, or standard link. * * @since 1.15 * * @param array $atts { * @type string $action What type of link to generate. Options: `read`, `edit`, and `delete`. Default: `read` * @type string $view_id Define the ID for the View. If not set, use current View ID, if exists. * @type string $entry_id ID of the entry to edit. If undefined, uses the current entry ID, if exists. * @type string $post_id ID of the base post or page to use for an embedded View * @type string $link_atts Pass anchor tag attributes (`target=_blank` to open Edit Entry link in a new window, for example) * @type string $return What should the shortcode return: link HTML (`html`) or the URL (`url`). Default: `html` * @type string $field_values Only used for `action="edit"`. Parameters to pass in to the prefill data in Edit Entry form. Uses the same format as Gravity Forms "Allow field to be populated dynamically" {@see https://www.gravityhelp.com/documentation/article/allow-field-to-be-populated-dynamically/ } * } * * @param string|null $content Used as link anchor text, if specified. * @param string $context Current shortcode being called. Not used. * * @return null|string If admin or an error occurred, returns null. Otherwise, returns entry link output. If `$atts['return']` is 'url', the entry link URL. Otherwise, entry link `<a>` HTML tag. */ private function shortcode($atts, $content = null, $context = 'gv_entry_link') { // Don't process when saving post. Keep processing if it's admin-ajax.php if (!class_exists('GravityView_Plugin') || GravityView_Plugin::is_admin()) { return null; } // Make sure GV is loaded if (!class_exists('GravityView_frontend') || !class_exists('GravityView_View')) { do_action('gravityview_log_error', __METHOD__ . ' GravityView_frontend or GravityView_View do not exist.'); return null; } $this->settings = shortcode_atts(self::$defaults, $atts, $context); $this->view_id = empty($this->settings['view_id']) ? GravityView_View::getInstance()->getViewId() : absint($this->settings['view_id']); if (empty($this->view_id)) { do_action('gravityview_log_error', __METHOD__ . ' A View ID was not defined and we are not inside a View'); return null; } $this->entry = $this->get_entry($this->settings['entry_id']); do_action('gravityview_log_debug', __METHOD__ . ' ' . $context . ' $atts: ', $atts); if (!$this->has_cap()) { do_action('gravityview_log_error', __METHOD__ . ' User does not have the capability to ' . esc_attr($this->settings['action']) . ' this entry: ' . $this->entry['id']); return null; } $url = $this->get_url(); if (!$url) { do_action('gravityview_log_error', __METHOD__ . ' Link returned false; View or Post may not exist.'); return false; } // Get just the URL, not the tag if ('url' === $this->settings['return']) { return $url; } $link_atts = $this->get_link_atts(); $link_text = $this->get_anchor_text($content); return gravityview_get_link($url, $link_text, $link_atts); }
/** * @param array $atts User defined attributes in shortcode tag. * @param null $content * @param string $shortcode_tag * * @return string|null */ public function shortcode($atts = array(), $content = NULL, $shortcode_tag = '') { // Don't process except on frontend if (GravityView_Plugin::is_admin()) { return null; } $this->passed_atts = $atts; $this->passed_content = $content; $this->shortcode = $shortcode_tag; $this->parse_atts(); // We need an "if" if (false === $this->if) { do_action('gravityview_log_error', __METHOD__ . ' $atts->if is empty.', $this->atts); return null; } $setup = $this->setup_operation_and_comparison(); // We need an operation and comparison value if (!$setup) { do_action('gravityview_log_error', __METHOD__ . ' No valid operators were passed.', $this->atts); return null; } // Set the content and else_content $this->set_content_and_else_content(); // Check if it's a match $this->set_is_match(); // Return the value! return $this->get_output(); }
/** * Wrapper function to make sure GravityView_Extension has loaded * @return void */ function gv_extension_advanced_filtering_load() { if (!class_exists('GravityView_Extension')) { if (class_exists('GravityView_Plugin') && is_callable(array('GravityView_Plugin', 'include_extension_framework'))) { GravityView_Plugin::include_extension_framework(); } else { // We prefer to use the one bundled with GravityView, but if it doesn't exist, go here. include_once plugin_dir_path(__FILE__) . 'lib/class-gravityview-extension.php'; } } class GravityView_Advanced_Filtering extends GravityView_Extension { protected $_title = 'Advanced Filtering'; protected $_version = '1.0.11'; protected $_min_gravityview_version = '1.7.1'; /** * @since 1.0.11 * @type int */ protected $_item_id = 30; protected $_path = __FILE__; function add_hooks() { add_action('gravityview_metabox_filter_after', array($this, 'render_metabox')); // Admin_Views::add_scripts_and_styles() runs at 999 add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'), 1100); add_action('admin_print_footer_scripts', array($this, 'print_javascript'), 1100); // Add the magic filter add_filter('gravityview_search_criteria', array($this, 'filter_search_criteria'), 100, 3); add_filter('gravityview_noconflict_scripts', array($this, 'no_conflict_filter')); } /** * Add the scripts to the no-conflict mode whitelist * @param array $scripts Array of script keys * @return array Modified array */ function no_conflict_filter($scripts) { $scripts[] = 'gform_tooltip_init'; $scripts[] = 'gform_field_filter'; $scripts[] = 'gform_forms'; $scripts[] = 'gravityview_adv_filter_admin'; return $scripts; } /** * Modify search criteria * @param array $criteria Existing search criteria array, if any * @param [type] $form_ids Form IDs for the search * @param [type] $passed_view_id (optional) * @return [type] [description] */ function filter_search_criteria($criteria, $form_ids = null, $passed_view_id = NULL) { global $gravityview_view; if (is_admin() && (!defined('DOING_AJAX') || defined('DOING_AJAX') && !DOING_AJAX)) { return $criteria; } $view_id = !empty($passed_view_id) ? $passed_view_id : GravityView_View::getInstance()->getViewId(); if (empty($view_id)) { do_action('gravityview_log_error', 'GravityView_Advanced_Filtering[filter_search_criteria] Empty View ID.', $gravityview_view); $criteria['search_criteria']['field_filters'][] = self::get_lock_filter(); $criteria['search_criteria']['field_filters']['mode'] = 'all'; return $criteria; } $view_filters = self::get_view_filter_vars($view_id); if (!empty($view_filters) && is_array($view_filters)) { do_action('gravityview_log_debug', 'GravityView_Advanced_Filtering[filter_search_criteria] about to add search criteria', $view_filters); //sanitize filters - no empty search values foreach ($view_filters as $k => $filter) { // Don't use `empty()` because `0` is a valid value if ($k !== 'mode' && (!isset($filter['value']) || $filter['value'] === '')) { unset($view_filters[$k]); } } // add advanced filters if defined if (count($view_filters) > 1) { do_action('gravityview_log_debug', 'GravityView_Advanced_Filtering[filter_search_criteria] Added search criteria', $view_filters); foreach ($view_filters as $k => $filter) { if ($k !== 'mode') { $filter = self::parse_advanced_filters($filter, $view_id); $criteria['search_criteria']['field_filters'][] = $filter; } else { $criteria['search_criteria']['field_filters']['mode'] = $filter; } } } } else { do_action('gravityview_log_debug', 'GravityView_Advanced_Filtering[filter_search_criteria] No additional search criteria.'); } return $criteria; } /** * For some specific field types prepare the filter value before adding it to search criteria * @param array $filter * @return array */ static function parse_advanced_filters($filter = array(), $view_id = NULL) { if (empty($filter['key']) || !function_exists('gravityview_get_field_type') || !class_exists('GFCommon') || !class_exists('GravityView_API')) { return $filter; } if (!empty($view_id)) { $form_id = gravityview_get_form_id($view_id); $form = gravityview_get_form($form_id); } else { global $gravityview_view; $form = $gravityview_view->form; } // replace merge tags $filter['value'] = GravityView_API::replace_variables($filter['value'], $form, array()); $field_type = gravityview_get_field_type($form, $filter['key']); switch ($field_type) { case 'date': $local_timestamp = GFCommon::get_local_timestamp(); $date = strtotime($filter['value'], $local_timestamp); if ($date) { $filter['value'] = date('Y-m-d', $date); } else { do_action('gravityview_log_error', __METHOD__ . ' - Date formatting passed to Advanced Filter is invalid', $filter['value']); } break; } return $filter; } /** * Creates a filter that should return zero results * @since 1.0.7 * @return array */ public static function get_lock_filter() { return array('key' => 'created_by', 'operator' => 'is', 'value' => 'Advanced Filter Force Zero Results Filter'); } /** * Store the filter settings in the `_gravityview_filters` post meta * @param int $post_id Post ID * @return void */ function save_post($post_id) { if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) { return; } // validate post_type if (!isset($_POST['post_type']) || 'gravityview' != $_POST['post_type']) { return; } $form_id = !empty($_POST['gravityview_form_id']) ? $_POST['gravityview_form_id'] : ''; $form = gravityview_get_form($form_id); $filters = GFCommon::get_field_filters_from_post($form); update_post_meta($post_id, '_gravityview_filters', $filters); } /** * Enqueue scripts on Views admin * @see advfilter-admin-views.js * @param [type] $hook [description] * @return [type] [description] */ function admin_enqueue_scripts($hook) { global $post; // Don't process any scripts below here if it's not a GravityView page. if (!gravityview_is_admin_page($hook) || empty($post->ID)) { return; } $form_id = gravityview_get_form_id($post->ID); if (empty($form_id)) { return; } $filter_settings = self::get_field_filters($post->ID); if (empty($filter_settings['field_filters']) || empty($filter_settings['init_filter_vars'])) { do_action('gravityview_log_error', '[print_javascript] Filter settings were not properly set', $filter_settings); return; } $script_debug = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '.min'; wp_enqueue_script('gravityview_adv_filter_admin', plugins_url('assets/js/advfilter-admin-views' . $script_debug . '.js', __FILE__), array('jquery', 'gform_field_filter'), $this->_version); wp_localize_script('gravityview_adv_filter_admin', 'gvAdvFilterVar', array('gformFieldFilters' => $filter_settings['field_filters'], 'gformInitFilter' => $filter_settings['init_filter_vars'])); } function tooltips($tooltips = array()) { $tooltips['gv_advanced_filter'] = array('title' => __('Advanced Filter', 'gravity-view-advanced-filter'), 'value' => wpautop(__('Limit what entries are visible based on entry values. The entries are filtered before the View is displayed. When users perform a search, results will first be filtered by these settings.', 'gravity-view-advanced-filter') . '<h6>' . __('Limit to Logged-in User Entries', 'gravity-view-advanced-filter') . '</h6>' . __('To limit entries to those created by the current user, select "Created By", "is" & "Logged-in User" from the drop-down menus.', 'gravity-view-advanced-filter') . ' ' . __('If you want to limit entries to those created by the current user, but allow the administrators to view all the entries, select "Logged-in User (disabled for admins)" from the drop-down menu.', 'gravity-view-advanced-filter'))); return $tooltips; } /** * Render the HTML container that will be replaced by the Javascript * @return void */ function render_metabox($settings = array()) { include plugin_dir_path(__FILE__) . 'partials/metabox.php'; } static function get_view_filter_vars($post_id, $admin_formatting = false) { $init_filter_vars = get_post_meta($post_id, '_gravityview_filters', true); if (empty($init_filter_vars)) { return false; } // migration purposes from the old version with JSON_ENCODE if (!is_array($init_filter_vars) && strpos($init_filter_vars, '{') === 0) { $init_filter_vars = json_decode($init_filter_vars, true); } // In the Admin, the Javascript requires special formatting. if ($admin_formatting && array_key_exists('mode', $init_filter_vars)) { // Re-set this below $mode = $init_filter_vars['mode']; unset($init_filter_vars['mode']); // GF stores the field filter data as a flat array. // We need to set the `filters` key with the fields $init_filter_vars = array('filters' => $init_filter_vars, 'mode' => $mode); // The Javascript expects the `field` key, not the `key` key. foreach ($init_filter_vars['filters'] as &$filter) { $filter['field'] = $filter['key']; } } // Only show listings created by the current user. // This will return no entries if the user is logged out. foreach ($init_filter_vars as $k => &$filter) { if (isset($filter['key']) && isset($filter['value']) && $filter['key'] === 'created_by' && in_array($filter['value'], array('created_by', 'created_by_or_admin'))) { /** * Customise the capabilities that define an Administrator able to view entries in frontend when filtered by Created_by * * @param array|string $capabilities List of admin capabilities * @param int $post_id View ID where the filter is set * * @since 1.0.9 */ $admin_caps = apply_filters('gravityview/adv_filter/admin_caps', array('manage_options', 'gravityforms_view_entries'), $post_id); if ($filter['value'] === 'created_by_or_admin' && GFCommon::current_user_can_any($admin_caps)) { unset($init_filter_vars[$k]); } else { $filter['value'] = get_current_user_id(); } } } return apply_filters('gravityview/adv_filter/view_filters', $init_filter_vars, $post_id); } static function get_field_filters($post_id) { $form_id = gravityview_get_form_id($post_id); $form = gravityview_get_form($form_id); // Fixes issue on Views screen when deleting a view if (empty($form)) { return; } $field_filters = GFCommon::get_field_filter_settings($form); if ($approved_column = GravityView_Admin_ApproveEntries::get_approved_column($form)) { $approved_column = intval(floor($approved_column)); } // Add currently logged in user option foreach ($field_filters as &$filter) { // Add negative match to approval column if ($approved_column && $filter['key'] === $approved_column) { $filter['operators'][] = 'isnot'; continue; } // Gravity Forms already creates a "User" option. // We don't care about specific user, just the logged in status. if ($filter['key'] === 'created_by') { // Update the default label to be more descriptive $filter['text'] = esc_attr__('Created By', 'gravity-view-advanced-filter'); $current_user_filters = array(array('text' => __('Logged-in User (disabled for Admins)', 'gravity-view-advanced-filter'), 'value' => 'created_by_or_admin'), array('text' => __('Logged-in User', 'gravity-view-advanced-filter'), 'value' => 'created_by')); foreach ($current_user_filters as $user_filter) { // Add to the beginning on the value options array_unshift($filter['values'], $user_filter); } } } $init_field_id = 0; $init_field_operator = "contains"; $default_init_filter_vars = array("mode" => "all", "filters" => array(array("field" => $init_field_id, "operator" => $init_field_operator, "value" => ''))); $view_filter_vars = self::get_view_filter_vars($post_id, true); $init_filter_vars = !empty($view_filter_vars) ? $view_filter_vars : $default_init_filter_vars; /** * allow field filters manipulation * @param array $field_filters configured filters */ $field_filters = apply_filters('gravityview/adv_filter/field_filters', $field_filters, $post_id); return array('field_filters' => $field_filters, 'init_filter_vars' => $init_filter_vars); } /** * Output the script necessary for the drop-down to work * @param string $hook Admin page $pagenow string * @return void */ function print_javascript($hook) { global $post; // Don't process any scripts below here if it's not a GravityView page. if (!gravityview_is_admin_page($hook) || empty($post->ID)) { return; } ?> <style type="text/css"> #entry_filters_warning { display: none; } #gform-no-filters { padding: 1em 0; cursor: pointer; width: 100%; } #gform-no-filters img { float:right; margin: 2px .25em; } #gv-advanced-filter .gform-field-filter { margin: .5em 0; } /** Text input filter */ #gv-advanced-filter input.gform-filter-value, #gv-advanced-filter select { margin: 0 .3em; width: auto; max-width: 32%; } #gv-advanced-filter .gform-field-filter .gform-add { margin: 0 5px 0 2px; } #gv-advanced-filter h3 { margin-bottom: .5em; padding-left: 0; } #gv-advanced-filter .description { margin-bottom: .5em; } </style> <?php } } // end class new GravityView_Advanced_Filtering(); }
/** * Handle whether to display notices in Multisite based on plugin activation status * * @uses GravityView_Plugin::is_network_activated * * @since 1.12 * * @return bool True: show the notices; false: don't show */ private function check_show_multisite_notices() { if (!is_multisite()) { return true; } // It's network activated but the user can't manage network plugins; they can't do anything about it. if (GravityView_Plugin::is_network_activated() && !is_main_site()) { return false; } // or they don't have admin capabilities if (!is_super_admin()) { return false; } return true; }
/** * * @param $view_id */ public function render_widget_hooks($view_id) { if (empty($view_id) || 'single' == gravityview_get_context()) { do_action('gravityview_log_debug', __METHOD__ . ' - Not rendering widgets; single entry'); return; } $view_data = gravityview_get_current_view_data($view_id); // get View widget configuration $widgets = (array) $view_data['widgets']; switch (current_filter()) { default: case 'gravityview_before': $zone = 'header'; break; case 'gravityview_after': $zone = 'footer'; break; } /** * Filter widgets not in the current zone * @since 1.16 */ foreach ($widgets as $key => $widget) { // The widget isn't in the current zone if (false === strpos($key, $zone)) { unset($widgets[$key]); } } /** * Prevent output if no widgets to show. * @since 1.16 */ if (empty($widgets)) { do_action('gravityview_log_debug', sprintf('No widgets for View #%s', $view_id)); return; } // Prevent being called twice if (did_action($zone . '_' . $view_id . '_widgets')) { do_action('gravityview_log_debug', sprintf('%s - Not rendering %s; already rendered', __METHOD__, $zone . '_' . $view_id . '_widgets')); return; } $rows = GravityView_Plugin::get_default_widget_areas(); // TODO: Move to sep. method, use an action instead wp_enqueue_style('gravityview_default_style'); $default_css_class = 'gv-grid gv-widgets-' . $zone; if (0 === GravityView_View::getInstance()->getTotalEntries()) { $default_css_class .= ' gv-widgets-no-results'; } /** * @filter `gravityview/widgets/wrapper_css_class` The CSS class applied to the widget container `<div>`. * @since 1.16.2 * @param string $css_class Default: `gv-grid gv-widgets-{zone}` where `{zone}` is replaced by the current `$zone` value. If the View has no results, adds ` gv-widgets-no-results` * @param string $zone Current widget zone, either `header` or `footer` * @param array $widgets Array of widget configurations for the current zone, as set by `gravityview_get_current_view_data()['widgets']` */ $css_class = apply_filters('gravityview/widgets/wrapper_css_class', $default_css_class, $zone, $widgets); $css_class = gravityview_sanitize_html_class($css_class); // TODO Convert to partials ?> <div class="<?php echo $css_class; ?> "> <?php foreach ($rows as $row) { foreach ($row as $col => $areas) { $column = $col == '2-2' ? '1-2 gv-right' : $col . ' gv-left'; ?> <div class="gv-grid-col-<?php echo esc_attr($column); ?> "> <?php if (!empty($areas)) { foreach ($areas as $area) { if (!empty($widgets[$zone . '_' . $area['areaid']])) { foreach ($widgets[$zone . '_' . $area['areaid']] as $widget) { do_action("gravityview_render_widget_{$widget['id']}", $widget); } } } } ?> </div> <?php } // $row ?> <?php } // $rows ?> </div> <?php /** * Prevent widgets from being called twice. * Checking for loop_start prevents themes and plugins that pre-process shortcodes from triggering the action before displaying. Like, ahem, the Divi theme and WordPress SEO plugin */ if (did_action('loop_start')) { do_action($zone . '_' . $view_id . '_widgets'); } }