/**
 * Views-Shortcode: wpv-if
 *
 * Description: Conditional shortcode to be used to display a specific area
 * based on a custom field condition. \n
 * Supported actions and symbols:\n
 * Integer and floating-point numbers \n
 * Math operators: +, -, *, / \n
 * Comparison operators: <, >, =, <=, >=, != \n
 * Boolean operators: AND, OR, NOT \n
 * Nested expressions - several levels of parentheses \n
 * Variables defined as shortcode parameters starting with a dollar sign \n
 * empty() function that checks for empty or non-existing fields
 *
 * Parameters:
 * 'condition' => Define expected result from evaluate - either true or false
 * 'evaluate' => Evaluate expression with fields involved, sample use: "($field1 > $field2) AND !empty($field3)"
 * 'debug' => Enable debug to display error messages in the shortcode 
 * 'fieldX' => Define fields to be taken into account during evaluation 
 *
 * Example usage:
 * [wpv-if evaluate="boolean condition"]
 *    Execute code for true
 * [/wpv-if]
 * Sing a variable and comparing its value to a constant
 * [wpv-if f1="wpcf-condnum1" evaluate="$f1 = 1" debug="true"]Number1=1[/wpv-if]
 * Two numeric variables in a mathematical expression with boolean operators
 * [wpv-if f1="wpcf-condnum1" f2="wpcf-condnum2" evaluate="(2 < 3 AND (((3+$f2)/2) > 3 OR NOT($f1 > 3)))" debug="true"]Visible block[/wpv-if]
 * Compare custom field with a value
 * [wpv-if f1="wpcf-condstr1" evaluate="$f1 = 'My text'" debug="true"]Text1='My text' [/wpv-if]
 * Display condition if evaluates to false (use instead of else-if)
 * [wpv-if condition="false" evaluate="2 > 3"] 2 > 3 [/wpv-if]
 * Custom function support
 * [wpv-if evaluate="my_func() = '1'"]my_func returns 1[/wpv-if]
 *
 * Link:
 * <a href="http://wp-types.com/documentation/user-guides/conditional-html-output-in-views/?utm_source=viewsplugin&utm_campaign=views&utm_medium=views-conditional-help-link&utm_term=Conditional HTML output in Views">Conditional HTML output in Views</a>
 *
 * Note:
 *
 */
function wpv_shortcode_wpv_if($args, $content)
{
    $result = wpv_condition($args);
    extract(shortcode_atts(array('evaluate' => FALSE, 'debug' => FALSE, 'condition' => TRUE), $args));
    $condition = $condition == 'true' || $condition === TRUE ? true : false;
    // show the view area if condition corresponds to the evaluate returned result 1=1 or 0=0
    if ($result === true && $condition || $result === false && !$condition) {
        $out = wpv_do_shortcode($content);
        apply_filters('wpv_shortcode_debug', 'wpv-if', json_encode($args), '', 'Conditional output: evaluated to true', $out);
        return $out;
    } else {
        // output empty string or the error message if debug is true
        // empty for different condition and evaluate result
        if ($result === false && $condition || $result === true && !$condition) {
            apply_filters('wpv_shortcode_debug', 'wpv-if', json_encode($args), '', 'Conditional output: evaluated to false');
            return '';
        } else {
            if ($debug) {
                return $result;
            } else {
                return '';
            }
            apply_filters('wpv_shortcode_debug', 'wpv-if', json_encode($args), '', 'Conditional output: error', $result);
        }
    }
}
Exemple #2
0
 /**
  * Main conditinal evaluation function.
  * 
  * This is important break-point.
  * 
  * @since 1.2
  * @version 0.1
  * @param type $o
  * @return boolean 
  */
 function evaluate($o)
 {
     // Set vars
     $post = $o->post;
     $field = $o->cf;
     /*
      * 
      * Since Types 1.2
      * We force initial value to be FALSE.
      * Better to have restricted than allowed because of sensitive data.
      * If conditional is set on field and it goes wrong - better to abort
      * so user can report bug without exposing his content.
      */
     $passed = false;
     if (empty($post->ID)) {
         /*
          * 
          * Keep all forbidden if post is not saved.
          */
         $passed = false;
         /*
          * 
          * 
          * 
          * 
          * 
          * 
          * 
          * 
          * 
          * VIEWS
          * 
          * Custom call uses Views code
          * wpv_filter_parse_date()
          * wpv_condition()
          */
     } else {
         if (isset($field['data']['conditional_display']['custom_use'])) {
             /*
              * 
              * 
              * More malformed forbids
              */
             if (empty($field['data']['conditional_display']['custom'])) {
                 return false;
             }
             /*
              * 
              * 
              * Filter meta values (switch them with $_POST values)
              * Used by Views, Types do not need it.
              */
             add_filter('get_post_metadata', 'wpcf_cd_meta_ajax_validation_filter', 10, 4);
             /*
              * 
              * Set statement
              */
             $evaluate = trim(stripslashes($field['data']['conditional_display']['custom']));
             // Check dates
             $evaluate = wpv_filter_parse_date($evaluate);
             // Add quotes = > < >= <= === <> !==
             $strings_count = preg_match_all('/[=|==|===|<=|<==|<===|>=|>==|>===|\\!===|\\!==|\\!=|<>]\\s(?!\\$)(\\w*)[\\)|\\$|\\W]/', $evaluate, $matches);
             if (!empty($matches[1])) {
                 foreach ($matches[1] as $temp_match) {
                     $temp_replace = is_numeric($temp_match) ? $temp_match : '\'' . $temp_match . '\'';
                     $evaluate = str_replace(' ' . $temp_match . ')', ' ' . $temp_replace . ')', $evaluate);
                 }
             }
             preg_match_all('/\\$([^\\s]*)/', $field['data']['conditional_display']['custom'], $matches);
             if (empty($matches)) {
                 /*
                  * 
                  * If statement false
                  */
                 $passed = false;
             } else {
                 /*
                  * 
                  * 
                  * If statement right, check condition
                  */
                 $fields = array();
                 foreach ($matches[1] as $field_name) {
                     /*
                      * 
                      * 
                      * This field value is checked
                      */
                     $f = wpcf_admin_fields_get_field(trim(strval($field_name)));
                     if (empty($f)) {
                         return false;
                     }
                     $c = new WPCF_Field();
                     $c->set($post, $f);
                     // Set field
                     $fields[$field_name] = $c->slug;
                 }
                 $fields['evaluate'] = $evaluate;
                 $check = wpv_condition($fields);
                 /*
                  * 
                  * 
                  * Views return string malformed,
                  * boolean if call completed.
                  */
                 if (!is_bool($check)) {
                     $passed = false;
                 } else {
                     $passed = $check;
                 }
             }
             /*
              * 
              * 
              * Remove filter meta values
              */
             remove_filter('get_post_metadata', 'wpcf_cd_meta_ajax_validation_filter', 10, 4);
         } else {
             /*
              * 
              * 
              * 
              * 
              * 
              * 
              * 
              * 
              * TYPES
              * 
              * If not custom code, use Types built-in check.
              * wpcf_cd_admin_compare()
              */
             $passed_all = true;
             $passed_one = false;
             // Basic check
             if (empty($field['data']['conditional_display']['conditions'])) {
                 return false;
             }
             // Keep count to see if OR/AND relation needed
             $count = count($field['data']['conditional_display']['conditions']);
             foreach ($field['data']['conditional_display']['conditions'] as $condition) {
                 /*
                  * 
                  * 
                  * Malformed condition and should be treated as forbidden
                  */
                 if (!isset($condition['field']) || !isset($condition['operation']) || !isset($condition['value'])) {
                     $passed_one = false;
                     continue;
                 }
                 /*
                  * 
                  * 
                  * This field value is checked
                  */
                 $f = wpcf_admin_fields_get_field(trim(strval($condition['field'])));
                 if (empty($f)) {
                     return false;
                 }
                 $c = new WPCF_Field();
                 $c->set($post, $f);
                 /*
                  * 
                  * Since Types 1.2
                  * meta is property of WPCF_Field::$__meta
                  * 
                  * BREAKPOINT
                  * This is where values for evaluation are set.
                  * Please do not allow other places - use hooks.
                  */
                 $value = defined('DOING_AJAX') ? $c->_get_meta('POST') : $c->__meta;
                 /*
                  * 
                  * Apply filters
                  */
                 $value = apply_filters('wpcf_conditional_display_compare_meta_value', $value, $c->cf['id'], $condition['operation'], $c->slug, $post);
                 $condition['value'] = apply_filters('wpcf_conditional_display_compare_condition_value', $condition['value'], $c->cf['id'], $condition['operation'], $c->slug, $post);
                 /*
                  * 
                  * 
                  * Call built-in Types compare func
                  */
                 $passed = wpcf_cd_admin_compare($condition['operation'], $value, $condition['value']);
                 if (!$passed) {
                     $passed_all = false;
                 } else {
                     $passed_one = true;
                 }
             }
             /*
              * 
              * 
              * Check OR/AND relation
              */
             if ($count > 1) {
                 if (!$passed_all && $field['data']['conditional_display']['relation'] == 'AND') {
                     $passed = false;
                 }
                 if (!$passed_one && $field['data']['conditional_display']['relation'] == 'OR') {
                     $passed = false;
                 }
             }
         }
     }
     return (bool) $passed;
 }
/**
 * Checks if there is conditional display.
 * 
 * @param type $element
 * @param type $field
 * @param type $post
 * @return type 
 */
function wpcf_cd_post_edit_field_filter($element, $field, $post, $context = 'group')
{
    if (defined('DOING_AJAX') && $context == 'repetitive') {
        return $element;
    }
    if (!empty($field['data']['conditional_display']['conditions'])) {
        add_action('admin_head', 'wpcf_cd_add_field_js');
        $passed = true;
        if (empty($post->ID)) {
            $passed = false;
        } else {
            if (isset($field['data']['conditional_display']['custom_use'])) {
                if (empty($field['data']['conditional_display']['custom'])) {
                    return array();
                }
                $evaluate = trim(stripslashes($field['data']['conditional_display']['custom']));
                // Check dates
                $evaluate = wpv_filter_parse_date($evaluate);
                // Add quotes = > < >= <= === <> !==
                $strings_count = preg_match_all('/[=|==|===|<=|<==|<===|>=|>==|>===|\\!===|\\!==|\\!=|<>]\\s(?!\\$)(\\w*)[\\)|\\$|\\W]/', $evaluate, $matches);
                if (!empty($matches[1])) {
                    foreach ($matches[1] as $temp_match) {
                        $temp_replace = is_numeric($temp_match) ? $temp_match : '\'' . $temp_match . '\'';
                        $evaluate = str_replace(' ' . $temp_match . ')', ' ' . $temp_replace . ')', $evaluate);
                    }
                }
                preg_match_all('/\\$([^\\s]*)/', $field['data']['conditional_display']['custom'], $matches);
                if (empty($matches)) {
                    $passed = false;
                } else {
                    $fields = array();
                    foreach ($matches[1] as $key => $field_name) {
                        $fields[$field_name] = wpcf_types_get_meta_prefix(wpcf_admin_fields_get_field($field_name)) . $field_name;
                    }
                    $fields['evaluate'] = $evaluate;
                    $check = wpv_condition($fields);
                    if (!is_bool($check)) {
                        $passed = false;
                    } else {
                        $passed = $check;
                    }
                }
            } else {
                $passed_all = true;
                $passed_one = false;
                foreach ($field['data']['conditional_display']['conditions'] as $condition) {
                    // This is malformed condition and should be treated as passed
                    // @TODO Approve it
                    if (!isset($condition['field']) || !isset($condition['operation']) || !isset($condition['value'])) {
                        $passed_one = true;
                        continue;
                    }
                    $value = get_post_meta($post->ID, wpcf_types_get_meta_prefix($condition['field']) . $condition['field'], true);
                    $value = apply_filters('wpcf_conditional_display_compare_meta_value', $value, $condition['field'], $condition['operation'], $field['slug'], $post);
                    $condition['value'] = apply_filters('wpcf_conditional_display_compare_condition_value', $condition['value'], $condition['field'], $condition['operation'], $field['slug'], $post);
                    $check = wpcf_cd_admin_compare($condition['operation'], $value, $condition['value']);
                    if (!$check) {
                        $passed_all = false;
                    } else {
                        $passed_one = true;
                    }
                }
                if (!$passed_all && $field['data']['conditional_display']['relation'] == 'AND') {
                    $passed = false;
                }
                if (!$passed_one && $field['data']['conditional_display']['relation'] == 'OR') {
                    $passed = false;
                }
            }
        }
        if (!$passed) {
            $wrap = '<div class="wpcf-cd wpcf-cd-failed" style="display:none;">';
            $element['__wpcf_cd_status'] = 'failed';
        } else {
            $wrap = '<div class="wpcf-cd wpcf-cd-passed">';
            $element['__wpcf_cd_status'] = 'passed';
        }
        if (isset($element['#before'])) {
            $element['#before'] = $wrap . $element['#before'];
        } else {
            $element['#before'] = $wrap;
        }
        if (isset($element['#after'])) {
            $element['#after'] = $element['#after'] . '</div>';
        } else {
            $element['#after'] = '</div>';
        }
    }
    return $element;
}
/**
 * Filters groups on post edit page.
 * 
 * @param type $groups
 * @param type $post
 * @return type 
 */
function wpcf_cd_post_groups_filter($groups, $post, $context)
{
    if ($context != 'group') {
        return $groups;
    }
    foreach ($groups as $key => &$group) {
        $meta_conditional = !isset($group['conditional_display']) ? get_post_meta($group['id'], '_wpcf_conditional_display', true) : $group['conditional_display'];
        if (!empty($meta_conditional['conditions'])) {
            $group['conditional_display'] = $meta_conditional;
            add_action('admin_head', 'wpcf_cd_add_group_js');
            if (empty($post->ID)) {
                $group['_conditional_display'] = 'failed';
                continue;
            }
            $passed = true;
            if (isset($group['conditional_display']['custom_use'])) {
                if (empty($group['conditional_display']['custom'])) {
                    $group['_conditional_display'] = 'failed';
                    continue;
                }
                $evaluate = trim(stripslashes($group['conditional_display']['custom']));
                // Check dates
                $evaluate = wpv_filter_parse_date($evaluate);
                // Add quotes = > < >= <= === <> !==
                $strings_count = preg_match_all('/[=|==|===|<=|<==|<===|>=|>==|>===|\\!===|\\!==|\\!=|<>]\\s(?!\\$)(\\w*)[\\)|\\$|\\W]/', $evaluate, $matches);
                if (!empty($matches[1])) {
                    foreach ($matches[1] as $temp_match) {
                        $temp_replace = is_numeric($temp_match) ? $temp_match : '\'' . $temp_match . '\'';
                        $evaluate = str_replace(' ' . $temp_match . ')', ' ' . $temp_replace . ')', $evaluate);
                    }
                }
                preg_match_all('/\\$([^\\s]*)/', $group['conditional_display']['custom'], $matches);
                if (empty($matches)) {
                    $group['_conditional_display'] = 'failed';
                    continue;
                }
                $fields = array();
                foreach ($matches[1] as $key => $field_name) {
                    $fields[$field_name] = wpcf_types_get_meta_prefix(wpcf_admin_fields_get_field($field_name)) . $field_name;
                    wpcf_cd_add_group_js('add', $field_name, '', '', $group['id']);
                }
                $fields['evaluate'] = $evaluate;
                $check = wpv_condition($fields);
                $passed = $check;
                if (!is_bool($check)) {
                    $passed = false;
                    $group['_conditional_display'] = 'failed';
                } else {
                    if ($check) {
                        $group['_conditional_display'] = 'passed';
                    } else {
                        $group['_conditional_display'] = 'failed';
                    }
                }
            } else {
                $passed_all = true;
                $passed_one = false;
                foreach ($group['conditional_display']['conditions'] as $condition) {
                    // Load field
                    $field = wpcf_admin_fields_get_field($condition['field']);
                    wpcf_fields_type_action($field['type']);
                    wpcf_cd_add_group_js('add', $condition['field'], $condition['value'], $condition['operation'], $group['id']);
                    $value = get_post_meta($post->ID, wpcf_types_get_meta_prefix($condition['field']) . $condition['field'], true);
                    $value = apply_filters('wpcf_conditional_display_compare_meta_value', $value, $condition['field'], $condition['operation'], $key, $post);
                    $condition['value'] = apply_filters('wpcf_conditional_display_compare_condition_value', $condition['value'], $condition['field'], $condition['operation'], $key, $post);
                    $check = wpcf_cd_admin_compare($condition['operation'], $value, $condition['value']);
                    if (!$check) {
                        $passed_all = false;
                    } else {
                        $passed_one = true;
                    }
                }
                if (!$passed_all && $group['conditional_display']['relation'] == 'AND') {
                    $passed = false;
                }
                if (!$passed_one && $group['conditional_display']['relation'] == 'OR') {
                    $passed = false;
                }
            }
            if (!$passed) {
                $group['_conditional_display'] = 'failed';
            } else {
                $group['_conditional_display'] = 'passed';
            }
        }
    }
    return $groups;
}
/**
 * Checks if there is conditional display.
 * 
 * @param type $element
 * @param type $field
 * @param type $post
 * @return type 
 */
function wpcf_cd_post_edit_field_filter($element, $field, $post, $context = 'group')
{
    if ($context != 'group') {
        return $element;
    }
    if (!empty($field['data']['conditional_display']['conditions'])) {
        if (empty($post)) {
            return array();
        }
        $passed = true;
        if (isset($field['data']['conditional_display']['custom_use'])) {
            if (empty($field['data']['conditional_display']['custom'])) {
                return array();
            }
            preg_match_all('/\\$([^\\s]*)/', $field['data']['conditional_display']['custom'], $matches);
            if (empty($matches)) {
                return array();
            }
            $fields = array();
            foreach ($matches[1] as $key => $field_name) {
                $fields[$field_name] = wpcf_types_get_meta_prefix(wpcf_admin_fields_get_field($field_name)) . $field_name;
            }
            $fields['evaluate'] = trim($field['data']['conditional_display']['custom']);
            $check = wpv_condition($fields);
            if (!is_bool($check)) {
                return array();
            }
            $passed = $check;
        } else {
            $passed_all = true;
            $passed_one = false;
            foreach ($field['data']['conditional_display']['conditions'] as $condition) {
                $value = get_post_meta($post->ID, wpcf_types_get_meta_prefix($condition['field']) . $condition['field'], true);
                $check = wpcf_cd_admin_compare($condition['operation'], $value, $condition['value']);
                if (!$check) {
                    $passed_all = false;
                } else {
                    $passed_one = true;
                }
            }
            if (!$passed_all && $field['data']['conditional_display']['relation'] == 'AND') {
                $passed = false;
            }
            if (!$passed_one && $field['data']['conditional_display']['relation'] == 'OR') {
                $passed = false;
            }
        }
        if (!$passed) {
            return array();
        }
    }
    return $element;
}