isset( $rule['field'] ) && '' !== $rule['field'] ? (string) $rule['field'] : ( isset( $rule['fieldId'] ) ? (string) $rule['fieldId'] : '' ), 'operator' => ! empty( $rule['operator'] ) ? (string) $rule['operator'] : 'is', 'value' => isset( $rule['value'] ) && ! is_array( $rule['value'] ) ? (string) $rule['value'] : '', ); } if ( empty( $rules ) ) { return null; } $action = ! empty( $item['logicAction'] ) ? $item['logicAction'] : ( ! empty( $legacy['action'] ) ? $legacy['action'] : 'show' ); $match = ! empty( $item['logicMatch'] ) ? $item['logicMatch'] : ( ! empty( $legacy['match'] ) ? $legacy['match'] : 'all' ); return array( 'action' => 'hide' === $action ? 'hide' : 'show', 'match' => 'any' === $match ? 'any' : 'all', 'rules' => $rules, ); } /** * True when the item (field, confirmation or notification) should apply. */ public static function passes( $item, $data ) { $logic = self::normalize( $item ); if ( ! $logic ) { return true; } $results = array(); foreach ( $logic['rules'] as $rule ) { if ( '' === $rule['fieldId'] ) { $results[] = false; continue; } $actual = isset( $data[ $rule['fieldId'] ] ) ? $data[ $rule['fieldId'] ] : null; $results[] = self::evaluate_rule( $rule['operator'], $actual, $rule['value'] ); } $met = 'all' === $logic['match'] ? ! in_array( false, $results, true ) : in_array( true, $results, true ); return 'show' === $logic['action'] ? $met : ! $met; } private static function to_list( $value ) { if ( ! is_array( $value ) ) { return null; } $flat = array(); array_walk_recursive( $value, function ( $v ) use ( &$flat ) { $flat[] = (string) $v; } ); return $flat; } private static function lower( $value ) { $value = trim( (string) $value ); return function_exists( 'mb_strtolower' ) ? mb_strtolower( $value ) : strtolower( $value ); } public static function evaluate_rule( $operator, $actual, $expected ) { $list = self::to_list( $actual ); if ( 'is_empty' === $operator ) { if ( null === $actual ) { return true; } if ( null !== $list ) { return 0 === count( array_filter( $list, 'strlen' ) ); } return '' === trim( (string) $actual ); } if ( 'is_not_empty' === $operator ) { return ! self::evaluate_rule( 'is_empty', $actual, $expected ); } $exp = self::lower( $expected ); switch ( $operator ) { case 'is_not': if ( null !== $list ) { foreach ( $list as $item ) { if ( self::lower( $item ) === $exp ) { return false; } } return true; } return self::lower( $actual ) !== $exp; case 'contains': case 'starts_with': case 'ends_with': $items = null !== $list ? $list : array( (string) $actual ); foreach ( $items as $item ) { $hay = self::lower( $item ); if ( 'contains' === $operator && ( '' === $exp || false !== strpos( $hay, $exp ) ) ) { return true; } if ( 'starts_with' === $operator && 0 === strpos( $hay, $exp ) ) { return true; } if ( 'ends_with' === $operator && ( '' === $exp || substr( $hay, -strlen( $exp ) ) === $exp ) ) { return true; } } return false; case 'greater_than': case 'less_than': if ( ! is_numeric( $actual ) || ! is_numeric( $expected ) ) { return false; } return 'greater_than' === $operator ? floatval( $actual ) > floatval( $expected ) : floatval( $actual ) < floatval( $expected ); case 'is': if ( null !== $list ) { foreach ( $list as $item ) { if ( self::lower( $item ) === $exp ) { return true; } } return false; } return self::lower( $actual ) === $exp; default: return true; } } }