• 1.
    <?php
  • 2.
    //flush_rewrite_rules( false );
  • 3.
     
  • 4.
    // Limit form submissions to prevent duplicates
  • 5.
    // http://gravitywiz.com/better-limit-submission-per-time-period-by-user-or-ip/
  • 6.
    /**
  • 7.
     * Gravity Wiz // Gravity Forms // Limit Submissions Per Time Period (by IP, User, Role, Form URL, or Field Value)
  • 8.
     *
  • 9.
     * Limit the number of times a form can be submitted per a specific time period. You modify this limit to apply to
  • 10.
     * the visitor's IP address, the user's ID, the user's role, a specific form URL, or the value of a specific field.
  • 11.
     * These "limiters" can be combined to create more complex limitations.
  • 12.
     *
  • 13.
     * @version	3.0
  • 14.
     * @author  David Smith <[email protected]>
  • 15.
     * @license GPL-2.0+
  • 16.
     * @link    http://gravitywiz.com/better-limit-submission-per-time-period-by-user-or-ip/
  • 17.
     */
  • 18.
    class GW_Submission_Limit {
  • 19.
     
  • 20.
        var $_args;
  • 21.
    	var $_notification_event;
  • 22.
     
  • 23.
    	private static $forms_with_individual_settings = array();
  • 24.
     
  • 25.
    	public function __construct( $args ) {
  • 26.
     
  • 27.
    	    // make sure we're running the required minimum version of Gravity Forms
  • 28.
    	    if( ! property_exists( 'GFCommon', 'version' ) || ! version_compare( GFCommon::$version, '1.8', '>=' ) )
  • 29.
    		    return;
  • 30.
     
  • 31.
            $this->_args = wp_parse_args( $args, array(
  • 32.
                'form_id'       => false,
  • 33.
    	        'form_ids'      => array(),
  • 34.
                'limit'         => 1,
  • 35.
                'limit_by'      => 'ip', // 'ip', 'user_id', 'role', 'embed_url', 'field_value'
  • 36.
                'time_period'   => 60 * 60 * 24, // integer in seconds or 'day', 'month', 'year' to limit to current day, month, or year respectively
  • 37.
                'limit_message' => __( 'Sorry, you have reached the submission limit for this form.' ),
  • 38.
    	        'apply_limit_per_form' => true,
  • 39.
    	        'enable_notifications' => false
  • 40.
            ) );
  • 41.
     
  • 42.
            if( ! is_array( $this->_args['limit_by'] ) ) {
  • 43.
                $this->_args['limit_by'] = array( $this->_args['limit_by'] );
  • 44.
            }
  • 45.
     
  • 46.
            if( empty( $this->_args['form_ids'] ) ) {
  • 47.
            	if( $this->_args['form_id'] === false ) {
  • 48.
            		$this->_args['form_ids'] = false;
  • 49.
    	        } elseif( ! is_array( $this->_args['form_id'] ) ) {
  • 50.
            		$this->_args['form_ids'] = array( $this->_args['form_id'] );
  • 51.
    	        } else {
  • 52.
    		        $this->_args['form_ids'] = $this->_args['form_id'];
  • 53.
    	        }
  • 54.
            }
  • 55.
     
  • 56.
    	    if( $this->_args['form_ids'] ) {
  • 57.
            	foreach( $this->_args['form_ids'] as $form_id ) {
  • 58.
    		        self::$forms_with_individual_settings[] = $form_id;
  • 59.
    	        }
  • 60.
    	    }
  • 61.
     
  • 62.
            add_action( 'init', array( $this, 'init' ) );
  • 63.
     
  • 64.
        }
  • 65.
     
  • 66.
    	public function init() {
  • 67.
     
  • 68.
    		add_filter( 'gform_pre_render', array( $this, 'pre_render' ) );
  • 69.
    		add_filter( 'gform_validation', array( $this, 'validate' ) );
  • 70.
     
  • 71.
    		if( $this->_args['enable_notifications'] ) {
  • 72.
     
  • 73.
    			$this->enable_notifications();
  • 74.
     
  • 75.
    			add_action( 'gform_after_submission', array( $this, 'maybe_send_limit_reached_notifications' ), 10, 2 );
  • 76.
     
  • 77.
    		}
  • 78.
     
  • 79.
    	}
  • 80.
     
  • 81.
    	public function pre_render( $form ) {
  • 82.
     
  • 83.
            if( ! $this->is_applicable_form( $form ) || ! $this->is_limit_reached( $form['id'] ) ) {
  • 84.
    	        return $form;
  • 85.
            }
  • 86.
     
  • 87.
            $submission_info = rgar( GFFormDisplay::$submission, $form['id'] );
  • 88.
     
  • 89.
            // if no submission, hide form
  • 90.
            // if submission and not valid, hide form
  • 91.
            // unless 'field_value' limiter is applied
  • 92.
            if( ( ! $submission_info || ! rgar( $submission_info, 'is_valid' ) ) && ! $this->is_limited_by_field_value() ) {
  • 93.
                add_filter( 'gform_get_form_filter_' . $form['id'], array( $this, 'get_limit_message' ), 10, 2 );
  • 94.
            }
  • 95.
     
  • 96.
            return $form;
  • 97.
     
  • 98.
        }
  • 99.
     
  • 100.
        public function get_limit_message() {
  • 101.
    		ob_start();
  • 102.
    		?>
  • 103.
    	    <div class="limit-message">
  • 104.
    		    <?php echo do_shortcode( $this->_args['limit_message'] ); ?>
  • 105.
    	    </div>
  • 106.
    		<?php
  • 107.
    	    return ob_get_clean();
  • 108.
        }
  • 109.
     
  • 110.
    	public function validate( $validation_result ) {
  • 111.
     
  • 112.
            if( ! $this->is_applicable_form( $validation_result['form'] ) || ! $this->is_limit_reached( $validation_result['form']['id'] ) ) {
  • 113.
                return $validation_result;
  • 114.
            }
  • 115.
     
  • 116.
            $validation_result['is_valid'] = false;
  • 117.
     
  • 118.
            if( $this->is_limited_by_field_value() ) {
  • 119.
    	        $field_ids = array_map( 'intval', $this->get_limit_field_ids() );
  • 120.
                foreach( $validation_result['form']['fields'] as &$field ) {
  • 121.
                    if( in_array( $field['id'], $field_ids ) ) {
  • 122.
                        $field['failed_validation'] = true;
  • 123.
                        $field['validation_message'] = do_shortcode( $this->_args['limit_message'] );
  • 124.
                    }
  • 125.
                }
  • 126.
            }
  • 127.
     
  • 128.
            return $validation_result;
  • 129.
        }
  • 130.
     
  • 131.
        public function is_limit_reached( $form_id ) {
  • 132.
            return $this->get_entry_count( $form_id ) >= $this->get_limit();
  • 133.
        }
  • 134.
     
  • 135.
        public function get_entry_count( $form_id ) {
  • 136.
    	    global $wpdb;
  • 137.
     
  • 138.
    	    $where = array();
  • 139.
    	    $join = array();
  • 140.
     
  • 141.
    	    $where[] = 'e.status = "active"';
  • 142.
     
  • 143.
    	    foreach( $this->_args['limit_by'] as $limiter ) {
  • 144.
    		    switch( $limiter ) {
  • 145.
    			    case 'role': // user ID is required when limiting by role
  • 146.
    			    case 'user_id':
  • 147.
    				    $where[] = $wpdb->prepare( 'e.created_by = %s', get_current_user_id() );
  • 148.
    				    break;
  • 149.
    			    case 'embed_url':
  • 150.
    				    $where[] = $wpdb->prepare( 'e.source_url = %s', GFFormsModel::get_current_page_url());
  • 151.
    				    break;
  • 152.
    			    case 'field_value':
  • 153.
     
  • 154.
    				    $values = $this->get_limit_field_values( $form_id, $this->get_limit_field_ids() );
  • 155.
     
  • 156.
    				    // if there is no value submitted for any of our fields, limit is never reached
  • 157.
    				    if( empty( $values ) ) {
  • 158.
    					    return false;
  • 159.
    				    }
  • 160.
     
  • 161.
    				    foreach( $values as $field_id => $value ) {
  • 162.
    					    $table_slug = sprintf( 'em%s', str_replace( '.', '_', $field_id ) );
  • 163.
    					    $join[]     = "INNER JOIN {$wpdb->prefix}gf_entry_meta {$table_slug} ON {$table_slug}.entry_id = e.id";
  • 164.
    					    $where[]    = $wpdb->prepare( "\n( ( {$table_slug}.meta_key BETWEEN %s AND %s ) AND {$table_slug}.meta_value = %s )", doubleval( $field_id ) - 0.001, doubleval( $field_id ) + 0.001, $value );
  • 165.
    				    }
  • 166.
     
  • 167.
    				    break;
  • 168.
    			    default:
  • 169.
    				    $where[] = $wpdb->prepare( 'ip = %s', GFFormsModel::get_ip() );
  • 170.
    		    }
  • 171.
    	    }
  • 172.
     
  • 173.
    	    if( $this->_args['apply_limit_per_form'] || ( ! $this->is_global( $form_id ) && count( $this->_args['form_ids'] ) <= 1 ) ) {
  • 174.
    		    $where[] = $wpdb->prepare( 'e.form_id = %d', $form_id );
  • 175.
    	    } else {
  • 176.
    		    $where[] = $wpdb->prepare( 'e.form_id IN( %s )', implode( ', ', $this->_args['form_ids'] ) );
  • 177.
    	    }
  • 178.
     
  • 179.
    	    $time_period = $this->_args['time_period'];
  • 180.
    	    $time_period_sql = false;
  • 181.
     
  • 182.
    	    if( $time_period === false ) {
  • 183.
    		    // no time period
  • 184.
    	    } else if( intval( $time_period ) > 0 ) {
  • 185.
    		    $time_period_sql = $wpdb->prepare( 'date_created BETWEEN DATE_SUB(utc_timestamp(), INTERVAL %d SECOND) AND utc_timestamp()', $this->_args['time_period'] );
  • 186.
    	    } else {
  • 187.
     
  • 188.
    	    	$gmt_offset  = get_option( 'gmt_offset' );
  • 189.
    	    	$date_func   = $gmt_offset < 0 ? 'DATE_SUB' : 'DATE_ADD';
  • 190.
    		    $hour_offset = abs( $gmt_offset );
  • 191.
     
  • 192.
    	    	$date_created_sql  = sprintf( '%s( date_created, INTERVAL %d HOUR )',    $date_func, $hour_offset );
  • 193.
    	    	$utc_timestamp_sql = sprintf( '%s( utc_timestamp(), INTERVAL %d HOUR )', $date_func, $hour_offset );
  • 194.
     
  • 195.
    		    switch( $time_period ) {
  • 196.
    			    case 'per_day':
  • 197.
    			    case 'day':
  • 198.
    				    $time_period_sql = "DATE( $date_created_sql ) = DATE( $utc_timestamp_sql )";
  • 199.
    				    break;
  • 200.
    			    case 'per_week':
  • 201.
    			    case 'week':
  • 202.
    				    $time_period_sql = "WEEK( $date_created_sql ) = WEEK( $utc_timestamp_sql )";
  • 203.
    			        $time_period_sql .= "AND YEAR( $date_created_sql ) = YEAR( $utc_timestamp_sql )";
  • 204.
    				    break;
  • 205.
    			    case 'per_month':
  • 206.
    			    case 'month':
  • 207.
    				    $time_period_sql = "MONTH( $date_created_sql ) = MONTH( $utc_timestamp_sql )";
  • 208.
    			        $time_period_sql .= "AND YEAR( $date_created_sql ) = YEAR( $utc_timestamp_sql )";
  • 209.
    				    break;
  • 210.
    			    case 'per_year':
  • 211.
    			    case 'year':
  • 212.
    				    $time_period_sql = "YEAR( $date_created_sql ) = YEAR( $utc_timestamp_sql )";
  • 213.
    				    break;
  • 214.
    		    }
  • 215.
     
  • 216.
    	    }
  • 217.
     
  • 218.
    	    if( $time_period_sql ) {
  • 219.
    		    $where[] = $time_period_sql;
  • 220.
    	    }
  • 221.
     
  • 222.
    	    $where = implode( ' AND ', $where );
  • 223.
    	    $join = implode( "\n", $join );
  • 224.
     
  • 225.
    	    $sql = "SELECT count( e.id )
  • 226.
                    FROM {$wpdb->prefix}gf_entry e
  • 227.
                    $join
  • 228.
                    WHERE $where";
  • 229.
     
  • 230.
    	    $entry_count = $wpdb->get_var( $sql );
  • 231.
     
  • 232.
    	    return $entry_count;
  • 233.
        }
  • 234.
     
  • 235.
        public function is_limited_by_field_value() {
  • 236.
            return in_array( 'field_value', $this->_args['limit_by'] );
  • 237.
        }
  • 238.
     
  • 239.
        public function get_limit_field_ids() {
  • 240.
     
  • 241.
    	    $limit = $this->_args['limit'];
  • 242.
     
  • 243.
    	    if( is_array( $limit ) ) {
  • 244.
    		    $field_ids = array_keys( $this->_args['limit'] );
  • 245.
    		    $field_ids = array( array_shift( $field_ids ) );
  • 246.
    	    } else {
  • 247.
    		    $field_ids = $this->_args['fields'];
  • 248.
    	    }
  • 249.
     
  • 250.
            return $field_ids;
  • 251.
        }
  • 252.
     
  • 253.
        public function get_limit_field_values( $form_id, $field_ids ) {
  • 254.
     
  • 255.
    	    $form   = GFAPI::get_form( $form_id );
  • 256.
    	    $values = array();
  • 257.
     
  • 258.
    	    foreach( $field_ids as $field_id ) {
  • 259.
     
  • 260.
    		    $field = GFFormsModel::get_field( $form, $field_id );
  • 261.
    		    if( ! $field ) {
  • 262.
    		    	continue;
  • 263.
    		    }
  • 264.
     
  • 265.
    		    $input_name = 'input_' . str_replace( '.', '_', $field_id );
  • 266.
    		    $value      = GFFormsModel::prepare_value( $form, $field, rgpost( $input_name ), $input_name, null );
  • 267.
     
  • 268.
    		    if( ! rgblank( $value ) ) {
  • 269.
    			    $values[ "$field_id" ] = $value;
  • 270.
    		    }
  • 271.
     
  • 272.
    	    }
  • 273.
     
  • 274.
            return $values;
  • 275.
        }
  • 276.
     
  • 277.
        public function get_limit() {
  • 278.
     
  • 279.
            $limit = $this->_args['limit'];
  • 280.
     
  • 281.
            if( $this->is_limited_by_field_value() ) {
  • 282.
                $limit = is_array( $limit ) ? array_shift( $limit ) : intval( $limit );
  • 283.
            } else if( in_array( 'role', $this->_args['limit_by'] ) ) {
  • 284.
                $limit = rgar( $limit, $this->get_user_role() );
  • 285.
            }
  • 286.
     
  • 287.
            return intval( $limit );
  • 288.
        }
  • 289.
     
  • 290.
        public function get_user_role() {
  • 291.
     
  • 292.
            $user = wp_get_current_user();
  • 293.
            $role = reset( $user->roles );
  • 294.
     
  • 295.
            return $role;
  • 296.
        }
  • 297.
     
  • 298.
    	public function enable_notifications() {
  • 299.
     
  • 300.
    		if( ! class_exists( 'GW_Notification_Event' ) ) {
  • 301.
     
  • 302.
    			_doing_it_wrong( 'GW_Inventory::$enable_notifications', __( 'Inventory notifications require the \'GW_Notification_Event\' class.' ), '1.0' );
  • 303.
     
  • 304.
    		} else {
  • 305.
     
  • 306.
    			$event_slug = implode( array_filter( array( "gw_submission_limit_limit_reached", $this->_args['form_id'] ) ) );
  • 307.
    			$event_name = GFForms::get_page() == 'notification_edit' ? __( 'Submission limit reached' ) : __( 'Event name is only populated on Notification Edit view; saves a DB call to get the form on every ' );
  • 308.
     
  • 309.
    			$this->_notification_event = new GW_Notification_Event( array(
  • 310.
    				'form_id'    => $this->_args['form_id'],
  • 311.
    				'event_name' => $event_name,
  • 312.
    				'event_slug' => $event_slug
  • 313.
    				//'trigger'    => array( $this, 'notification_event_listener' )
  • 314.
    			) );
  • 315.
     
  • 316.
    		}
  • 317.
     
  • 318.
    	}
  • 319.
     
  • 320.
    	public function maybe_send_limit_reached_notifications( $entry, $form ) {
  • 321.
     
  • 322.
    		if( $this->is_applicable_form( $form ) && $this->is_limit_reached( $form['id'] ) ) {
  • 323.
    			$this->send_limit_reached_notifications( $form, $entry );
  • 324.
    		}
  • 325.
     
  • 326.
    	}
  • 327.
     
  • 328.
    	public function send_limit_reached_notifications( $form, $entry ) {
  • 329.
     
  • 330.
    		$this->_notification_event->send_notifications( $this->_notification_event->get_event_slug(), $form, $entry, true );
  • 331.
     
  • 332.
    	}
  • 333.
     
  • 334.
    	public function is_applicable_form( $form ) {
  • 335.
     
  • 336.
    		$form_id          = isset( $form['id'] ) ? $form['id'] : $form;
  • 337.
    		$is_specific_form = ! $this->is_global( $form_id ) ? in_array( $form_id, $this->_args['form_ids'] ) : false;
  • 338.
     
  • 339.
    		return $this->is_global( $form_id ) || $is_specific_form;
  • 340.
    	}
  • 341.
     
  • 342.
    	public function is_global( $form) {
  • 343.
    		$form_id = isset( $form['id'] ) ? $form['id'] : $form;
  • 344.
    		return empty( $this->_args['form_ids'] ) && ! in_array( $form_id, self::$forms_with_individual_settings );
  • 345.
    	}
  • 346.
     
  • 347.
    }
  • 348.
     
  • 349.
    class GWSubmissionLimit extends GW_Submission_Limit { }
  • 350.
    new GW_Submission_Limit( array(
  • 351.
     'form_id' => 4,
  • 352.
     'limit_by' => 'field_value',
  • 353.
     'limit' => array(
  • 354.
     // "2" is your field ID, "6" is your limit for this field ID
  • 355.
     5 => 1
  • 356.
     ),
  • 357.
     'time_period' => false // forever!
  • 358.
    ) );
  • 359.
     
  • 360.
     
  • 361.
     
  • 362.
    //Remove Gutenberg Block Library CSS from loading on the frontend
  • 363.
    function smartwp_remove_wp_block_library_css(){
  • 364.
     wp_dequeue_style( 'wp-block-library' );
  • 365.
     wp_dequeue_style( 'wp-block-library-theme' );
  • 366.
    }
  • 367.
    add_action( 'wp_enqueue_scripts', 'smartwp_remove_wp_block_library_css' );
  • 368.
     
  • 369.
    // Change default excerpt ellipses
  • 370.
    function new_excerpt_more($more) {
  • 371.
        return '...';
  • 372.
    }
  • 373.
    add_filter('excerpt_more', 'new_excerpt_more');
  • 374.
     
  • 375.
     
  • 376.
    function themeprefix_show_cpt_archives( $query ) {
  • 377.
     if( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) {
  • 378.
     $query->set( 'post_type', array(
  • 379.
     'nav_menu_item', 'oped', 'video', 'recent-case', 'feat-press', 'post'
  • 380.
     ));
  • 381.
     return $query;
  • 382.
     }
  • 383.
    }
  • 384.
    add_filter( 'pre_get_posts', 'themeprefix_show_cpt_archives' );
  • 385.
     
  • 386.
     
  • 387.
    // Remove the word archive from archive page titles
  • 388.
    //https://www.binarymoon.co.uk/2017/02/hide-archive-title-prefix-wordpress/
  • 389.
    function hap_hide_the_archive_title( $title ) {
  • 390.
    	// Skip if the site isn't LTR, this is visual, not functional.
  • 391.
    	// Should try to work out an elegant solution that works for both directions.
  • 392.
    	if ( is_rtl() ) {
  • 393.
    		return $title;
  • 394.
    	}
  • 395.
    	// Split the title into parts so we can wrap them with spans.
  • 396.
    	$title_parts = explode( ': ', $title, 2 );
  • 397.
    	// Glue it back together again.
  • 398.
    	if ( ! empty( $title_parts[1] ) ) {
  • 399.
    		$title = wp_kses(
  • 400.
    			$title_parts[1],
  • 401.
    			array(
  • 402.
    				'span' => array(
  • 403.
    					'class' => array(),
  • 404.
    				),
  • 405.
    			)
  • 406.
    		);
  • 407.
    		$title = '<span class="screen-reader-text">' . esc_html( $title_parts[0] ) . ': </span>' . $title;
  • 408.
    	}
  • 409.
    	return $title;
  • 410.
    }
  • 411.
    add_filter( 'get_the_archive_title', 'hap_hide_the_archive_title' );
  • 412.
     
  • 413.
     
  • 414.
    function video_posttype() {
  • 415.
        register_post_type( 'video',
  • 416.
        // CPT Options
  • 417.
            array(
  • 418.
                'labels' => array(
  • 419.
                    'name' => __( 'Videos' ),
  • 420.
                    'singular_name' => __( 'Video' )
  • 421.
                ),
  • 422.
                // Features this CPT supports in Post Editor
  • 423.
                'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',),
  • 424.
                'public' => true,
  • 425.
                'has_archive' => true,
  • 426.
                'rewrite' => array('slug' => 'video'),
  • 427.
                'taxonomies' => array('category', 'post_tag'),
  • 428.
            )
  • 429.
        );
  • 430.
    }
  • 431.
    // Hooking up our function to theme setup
  • 432.
    add_action( 'init', 'video_posttype' );
  • 433.
     
  • 434.
    function oped_posttype() {
  • 435.
        register_post_type( 'oped',
  • 436.
        // CPT Options
  • 437.
            array(
  • 438.
                'labels' => array(
  • 439.
                    'name' => __( 'Op - Eds' ),
  • 440.
                    'singular_name' => __( 'Op - Ed' )
  • 441.
                ),
  • 442.
                // Features this CPT supports in Post Editor
  • 443.
                'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',),
  • 444.
                'public' => true,
  • 445.
                'has_archive' => true,
  • 446.
                'rewrite' => array('slug' => 'oped'),
  • 447.
                'taxonomies' => array('category'),
  • 448.
            )
  • 449.
        );
  • 450.
    }
  • 451.
    // Hooking up our function to theme setup
  • 452.
    add_action( 'init', 'oped_posttype' );
  • 453.
     
  • 454.
    function verdict_posttype() {
  • 455.
        register_post_type( 'verdict',
  • 456.
        // CPT Options
  • 457.
            array(
  • 458.
                'labels' => array(
  • 459.
                    'name' => __( 'Verdicts' ),
  • 460.
                    'singular_name' => __( 'Verdict' )
  • 461.
                ),
  • 462.
                // Features this CPT supports in Post Editor
  • 463.
                'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',),
  • 464.
                'public' => true,
  • 465.
                'has_archive' => true,
  • 466.
                'rewrite' => array('slug' => 'verdict'),
  • 467.
                'taxonomies' => array('category'),
  • 468.
            )
  • 469.
        );
  • 470.
    }
  • 471.
    // Hooking up our function to theme setup
  • 472.
    add_action( 'init', 'verdict_posttype' );
  • 473.
     
  • 474.
     
  • 475.
    function featPress_posttype() {
  • 476.
     
  • 477.
        register_post_type( 'feat-press',
  • 478.
        // CPT Options
  • 479.
            array(
  • 480.
                'labels' => array(
  • 481.
                    'name' => __( 'Press Coverage' ),
  • 482.
                    'singular_name' => __( 'Press Coverage' )
  • 483.
                ),
  • 484.
                // Features this CPT supports in Post Editor
  • 485.
                'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',),
  • 486.
                'public' => true,
  • 487.
                'has_archive' => true,
  • 488.
                'rewrite' => array('slug' => 'feat-press'),
  • 489.
                'taxonomies' => array('category'),
  • 490.
            )
  • 491.
        );
  • 492.
    }
  • 493.
    // Hooking up our function to theme setup
  • 494.
    add_action( 'init', 'featPress_posttype' );
  • 495.
     
  • 496.
    function recentCase_posttype() {
  • 497.
     
  • 498.
        register_post_type( 'recent-case',
  • 499.
        // CPT Options
  • 500.
            array(
  • 501.
                'labels' => array(
  • 502.
                    'name' => __( 'Recent Cases' ),
  • 503.
                    'singular_name' => __( 'Recent Case' )
  • 504.
                ),
  • 505.
                // Features this CPT supports in Post Editor
  • 506.
                'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields',),
  • 507.
                'public' => true,
  • 508.
                'has_archive' => true,
  • 509.
                'rewrite' => array('slug' => 'recent-case'),
  • 510.
                'taxonomies' => array('category'),
  • 511.
            )
  • 512.
        );
  • 513.
    }
  • 514.
    // Hooking up our function to theme setup
  • 515.
    add_action( 'init', 'recentCase_posttype' );
  • 516.
     
  • 517.
    /* 
  • 518.
    function create_posttype() {
  • 519.
     
  • 520.
        register_post_type( 'bio',
  • 521.
        // CPT Options
  • 522.
            array(
  • 523.
                'labels' => array(
  • 524.
                    'name' => __( 'Team Bios' ),
  • 525.
                    'singular_name' => __( 'Bio' )
  • 526.
                ),
  • 527.
                // Features this CPT supports in Post Editor
  • 528.
                'supports' => array( 'title', 'editor', 'page-attributes', 'thumbnail', 'revisions', 'custom-fields', ),
  • 529.
                'public' => true,
  • 530.
                'has_archive' => true,
  • 531.
                'rewrite' => array('slug' => 'bio'),
  • 532.
                'taxonomies' => array('alpha'),
  • 533.
            )
  • 534.
        );
  • 535.
    }
  • 536.
    // Hooking up our function to theme setup
  • 537.
    add_action( 'init', 'create_posttype' );*/
  • 538.
     
  • 539.
    /* Sort team members like page order i.e. the number assigned */
  • 540.
    function team_custom_post_order_sort( $query ){
  • 541.
      if ( $query->is_main_query() && is_post_type_archive( 'bio' )){
  • 542.
        $query->set( 'orderby', 'menu_order' );
  • 543.
        $query->set( 'order' , 'ASC' );
  • 544.
      }
  • 545.
    }
  • 546.
    add_action( 'pre_get_posts' , 'team_custom_post_order_sort' );
  • 547.
     
  • 548.
    // Remove pagination on team bio archive page
  • 549.
    function no_nopaging_leadership_index($query) {
  • 550.
        if (is_post_type_archive('bio') && is_main_query()) {
  • 551.
            $query->set('nopaging', 1);
  • 552.
        }
  • 553.
    }
  • 554.
    add_action('parse_query', 'no_nopaging_leadership_index');
  • 555.
     
  • 556.
    // Custom alpha taxonomy
  • 557.
    function alphaindex_alpha_tax() {
  • 558.
    	register_taxonomy( 'alpha',array (
  • 559.
    		0 => 'bio',
  • 560.
    	),
  • 561.
    	array( 'hierarchical' => false,
  • 562.
    		'label' => 'Alpha',
  • 563.
    		'show_ui' => false,
  • 564.
    		'query_var' => true,
  • 565.
    		'show_admin_column' => false,
  • 566.
    	) );
  • 567.
    }
  • 568.
    add_action('init', 'alphaindex_alpha_tax');
  • 569.
     
  • 570.
    // Automatically assign the right alpha taxonomy to bio posts on save
  • 571.
    function alphaindex_save_alpha( $post_id ) {
  • 572.
    	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
  • 573.
    	return;
  • 574.
    	//only run for bio
  • 575.
    	$slug = 'bio';
  • 576.
    	$letter = '';
  • 577.
    	// If this isn't a 'song' post, don't update it.
  • 578.
    	if ( isset( $_POST['post_type'] ) && ( $slug != $_POST['post_type'] ) )
  • 579.
    	return;
  • 580.
    	// Check permissions
  • 581.
    	if ( !current_user_can( 'edit_post', $post_id ) )
  • 582.
    	return;
  • 583.
    	// OK, we're authenticated: we need to find and save the data
  • 584.
    	$taxonomy = 'alpha';
  • 585.
    	if ( isset( $_POST['post_type'] ) ) {
  • 586.
    		// Get the title of the post
  • 587.
    		// $title = strtolower( $_POST['post_title'] );
  • 588.
     
  • 589.
        // Get the last word in a title https://stackoverflow.com/questions/18612872/get-the-last-word-of-a-string
  • 590.
        $string = strtolower( $_POST['post_title'] );
  • 591.
        $last_word_start = strrpos($string, ' ') + 1; // +1 so we don't include the space in our result
  • 592.
        $last_word = substr($string, $last_word_start); // $last_word = PHP.
  • 593.
     
  • 594.
    		// The next few lines remove A, An, or The from the start of the title
  • 595.
    		/*$splitTitle = explode(" ", $title);
  • 596.
    		$blacklist = array("an","a","the");
  • 597.
    		$splitTitle[0] = str_replace($blacklist,"",strtolower($splitTitle[0]));
  • 598.
    		$title = implode("", $splitTitle);*/
  • 599.
     
  • 600.
    		// Get the first letter of the title
  • 601.
    		//$letter = substr( $title, 0, 1 );
  • 602.
        $letter = substr( $last_word, 0, 1 );
  • 603.
     
  • 604.
    		// Set to 0-9 if it's a number
  • 605.
    		if ( is_numeric( $letter ) ) {
  • 606.
    			$letter = '0-9';
  • 607.
    		}
  • 608.
    	}
  • 609.
    	//set term as first letter of post title, lower case
  • 610.
    	wp_set_post_terms( $post_id, $letter, $taxonomy );
  • 611.
    }
  • 612.
    add_action( 'save_post', 'alphaindex_save_alpha' );
  • 613.
     
  • 614.
    // Enque Google Fonts
  • 615.
    function bg_load_google_fonts() {
  • 616.
    	wp_enqueue_style( 'google-fonts', '//fonts.googleapis.com/css?family=DM+Serif+Display:400', array(), '1' );
  • 617.
    }
  • 618.
    add_action( 'wp_enqueue_scripts', 'bg_load_google_fonts' );
  • 619.
     
  • 620.
    // Allows you to reference all blog type pages with is_blog() with conditional statements
  • 621.
    // https://wordpress.stackexchange.com/questions/107141/check-if-current-page-is-the-blog-page
  • 622.
    function is_blog () {
  • 623.
        return ( is_archive() || is_author() || is_category() || is_home() || is_single() || is_tag()) && 'post' == get_post_type();
  • 624.
    }
  • 625.
     
  • 626.
    // Prevents any user from accessing the Appearance > Customize menu
  • 627.
    add_filter('map_meta_cap', function($caps, $cap, $user_id, $args) {
  • 628.
        if ('customize' == $cap) return ['do_not_allow'];
  • 629.
        return $caps;
  • 630.
    }, 10, 4);
  • 631.
     
  • 632.
    function remove_unnecessary_wordpress_menus(){
  • 633.
        global $submenu;
  • 634.
        unset($submenu['themes.php'][11]);
  • 635.
        unset($submenu['themes.php'][12]);
  • 636.
    }
  • 637.
    add_action('admin_menu', 'remove_unnecessary_wordpress_menus', 999);
  • 638.
     
  • 639.
    /**
  • 640.
     * WCAG 2.0 Attributes for Dropdown Menus
  • 641.
     *
  • 642.
     * Adjustments to menu attributes tot support WCAG 2.0 recommendations
  • 643.
     * for flyout and dropdown menus.
  • 644.
     *
  • 645.
     * @ref https://www.w3.org/WAI/tutorials/menus/flyout/
  • 646.
     */
  • 647.
    function wcag_nav_menu_link_attributes( $atts, $item, $args, $depth ) {
  • 648.
     
  • 649.
        // Add [aria-haspopup] and [aria-expanded] to menu items that have children
  • 650.
        $item_has_children = in_array( 'menu-item-has-children', $item->classes );
  • 651.
        if ( $item_has_children ) {
  • 652.
            $atts['aria-haspopup'] = "true";
  • 653.
            $atts['aria-expanded'] = "false";
  • 654.
        }
  • 655.
     
  • 656.
        return $atts;
  • 657.
    }
  • 658.
    add_filter( 'nav_menu_link_attributes', 'wcag_nav_menu_link_attributes', 10, 4 );
  • 659.
     
  • 660.
    // Update Jquery to latest version
  • 661.
     function replace_core_jquery_version() {
  • 662.
        // Deregister WP core jQuery
  • 663.
    	wp_deregister_script( 'jquery' ); // the jquery handle is just an alias to load jquery-core with jquery-migrate
  • 664.
    	// Deregister WP jQuery
  • 665.
    	wp_deregister_script( 'jquery-core' );
  • 666.
    	// Deregister WP jQuery Migrate
  • 667.
    	wp_deregister_script( 'jquery-migrate' );
  • 668.
     
  • 669.
    	// Re-add latest jquery ver
  • 670.
    	wp_register_script( 'jquery', "//code.jquery.com/jquery-3.4.1.min.js", array(), '3.3.1' );
  • 671.
    	wp_enqueue_script('jquery');
  • 672.
     
  • 673.
    	// Re-add jquery migrate - only need if support for jquery ver older than 1.9 is needed
  • 674.
    	// wp_register_script( 'jquery-migrate', "https://code.jquery.com/jquery-migrate-3.1.0.min.js", array(), '3.1.0' );
  • 675.
    	// wp_enqueue_script('jquery-migrate');
  • 676.
    }
  • 677.
    add_action( 'wp_enqueue_scripts', 'replace_core_jquery_version' );
  • 678.
     
  • 679.
    // Disables tabindex on Gravity Forms
  • 680.
    add_filter( 'gform_tabindex', '__return_false' );
  • 681.
     
  • 682.
    // Changes input type=submit into a button for gravity forms and disables the button on submit
  • 683.
    add_filter( 'gform_next_button', 'input_to_button', 10, 2 );
  • 684.
    add_filter( 'gform_previous_button', 'input_to_button', 10, 2 );
  • 685.
    add_filter( 'gform_submit_button', 'form_submit_button', 10, 2 );
  • 686.
    function form_submit_button( $button, $form ) {
  • 687.
        return "<button class='btn btn--form d-block' id='gform_submit_button_{$form['id']}' onclick='var e=this;setTimeout(function(){e.disabled=true;},0);return true;'>Send Your Information</button>";
  • 688.
    }
  • 689.
     
  • 690.
    // Adds category class to body tag
  • 691.
    add_filter('body_class','add_category_to_single');
  • 692.
      function add_category_to_single($classes) {
  • 693.
        if (is_single() ) {
  • 694.
          global $post;
  • 695.
          foreach((get_the_category($post->ID)) as $category) {
  • 696.
            // add category slug to the $classes array
  • 697.
            $classes[] = $category->category_nicename;
  • 698.
          }
  • 699.
        }
  • 700.
        // return the $classes array
  • 701.
        return $classes;
  • 702.
      }
  • 703.
     
  • 704.
    //Excludes "News & Media" category from blog page
  • 705.
    function exclude_category($query) {
  • 706.
    if ( $query->is_home() ) {
  • 707.
    $query->set('cat', '-3');
  • 708.
    }
  • 709.
    return $query;
  • 710.
    }
  • 711.
    add_filter('pre_get_posts', 'exclude_category');
  • 712.
     
  • 713.
    // Gravity forms scroll to form on validation
  • 714.
    add_filter( 'gform_confirmation_anchor', '__return_true' );
  • 715.
     
  • 716.
    // Dequeue fontawesome free
  • 717.
    function dequeue_fontawesome_free() {
  • 718.
        wp_dequeue_style( 'wp-bootstrap-starter-fontawesome-cdn' );
  • 719.
        wp_deregister_style( 'wp-bootstrap-starter-fontawesome-cdn' );
  • 720.
    }
  • 721.
    add_action( 'wp_print_styles', 'dequeue_fontawesome_free' );
  • 722.
     
  • 723.
    // Dequeue boostrap
  • 724.
    function dequeue_boostrap() {
  • 725.
        wp_dequeue_style( 'wp-bootstrap-starter-bootstrap-css' );
  • 726.
        wp_deregister_style( 'wp-bootstrap-starter-bootstrap-css' );
  • 727.
    }
  • 728.
    add_action( 'wp_print_styles', 'dequeue_boostrap' );
  • 729.
     
  • 730.
    // Register + re-enque fontawesome pro
  • 731.
    function load_fontawesome_kit() {
  • 732.
      wp_register_script( 'font-awesome-pro', "https://kit.fontawesome.com/997b2a3cbf.js", array(), '5.10.2' );
  • 733.
      wp_enqueue_script('font-awesome-pro');
  • 734.
    }
  • 735.
    add_action( 'get_footer', 'load_fontawesome_kit', 0 );
  • 736.
     
  • 737.
    // Enque child theme styles
  • 738.
    function zblocks_enqueue_style() {
  • 739.
        wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/css/style.css' );
  • 740.
    }
  • 741.
    add_action( 'wp_enqueue_scripts', 'zblocks_enqueue_style', 1 );
  • 742.
     
  • 743.
    // Additional menu
  • 744.
    function register_my_menu() {
  • 745.
      register_nav_menu('dupe-menu',__( 'Secondary Menu' ));
  • 746.
    }
  • 747.
    add_action( 'init', 'register_my_menu' );
  • 748.
     
  • 749.
     
  • 750.
     
  • 751.
    // ACF Options Page
  • 752.
    if( function_exists('acf_add_options_page') ) {
  • 753.
    //acf_add_options_page();
  • 754.
     
  • 755.
      acf_add_options_page(array(
  • 756.
    		'page_title' 	=> 'Theme General Settings',
  • 757.
    		'menu_title'	=> 'Admin Settings',
  • 758.
    		'menu_slug' 	=> 'theme-general-settings',
  • 759.
    		'capability' => 'manage_options',
  • 760.
    		'redirect'		=> true,
  • 761.
    	));
  • 762.
     
  • 763.
    	acf_add_options_sub_page(array(
  • 764.
    		'page_title' 	=> 'Firm Information',
  • 765.
    		'menu_title'	=> 'Firm Info',
  • 766.
    		'parent_slug'	=> 'theme-general-settings'
  • 767.
    	));
  • 768.
     
  • 769.
      acf_add_options_sub_page(array(
  • 770.
    		'page_title' 	=> 'Theme Header Settings',
  • 771.
    		'menu_title'	=> 'Header',
  • 772.
    		'parent_slug'	=> 'theme-general-settings',
  • 773.
    	));
  • 774.
     
  • 775.
      acf_add_options_sub_page(array(
  • 776.
    		'page_title' 	=> 'Home Page Layout',
  • 777.
    		'menu_title'	=> 'Home Page Layout',
  • 778.
    		'parent_slug'	=> 'theme-general-settings',
  • 779.
    	));
  • 780.
     
  • 781.
    	acf_add_options_sub_page(array(
  • 782.
    		'page_title' 	=> 'Theme Footer Settings',
  • 783.
    		'menu_title'	=> 'Footer',
  • 784.
    		'parent_slug'	=> 'theme-general-settings',
  • 785.
    	));
  • 786.
    }
  • 787.
     
  • 788.
    // force scss to be processed on page load
  • 789.
    define('WP_SCSS_ALWAYS_RECOMPILE', true);
  • 790.
     
  • 791.
    //override parent theme posted_on
  • 792.
    if ( ! function_exists( 'wp_bootstrap_starter_posted_on' ) ) :
  • 793.
    /**
  • 794.
     * Prints HTML with meta information for the current post-date/time and author.
  • 795.
     */
  • 796.
    function wp_bootstrap_starter_posted_on() {
  • 797.
    	$time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';
  • 798.
    	if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) {
  • 799.
            $time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time>';
  • 800.
    	}
  • 801.
     
  • 802.
    	$time_string = sprintf( $time_string,
  • 803.
    		esc_attr( get_the_date( 'c' ) ),
  • 804.
    		esc_html( get_the_date() )
  • 805.
    	);
  • 806.
     
  • 807.
    	$posted_on = sprintf(
  • 808.
    		esc_html_x( 'Posted on %s', 'post date', 'wp-bootstrap-starter' ),
  • 809.
    		'<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">' . $time_string . '</a>'
  • 810.
    	);
  • 811.
     
  • 812.
    	$byline = sprintf(
  • 813.
    		esc_html_x( 'by %s', 'post author', 'wp-bootstrap-starter' ),
  • 814.
    		'<span class="author vcard"><a class="url fn n" href="' . esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '">' . esc_html( get_the_author() ) . '</a></span>'
  • 815.
    	);
  • 816.
     
  • 817.
    	echo '<span class="posted-on">' . $posted_on . '</span>'; // WPCS: XSS OK.
  • 818.
     
  • 819.
    }
  • 820.
    endif;
  • 821.
     
  • 822.
    if ( ! function_exists( 'wp_bootstrap_starter_entry_footer' ) ) :
  • 823.
    /**
  • 824.
     * Prints HTML with meta information for the categories, tags and comments.
  • 825.
     */
  • 826.
    function wp_bootstrap_starter_entry_footer() {
  • 827.
    	// Hide category and tag text for pages.
  • 828.
    	if ( 'post' === get_post_type() ) {
  • 829.
    		/* translators: used between list items, there is a space after the comma */
  • 830.
    		$categories_list = get_the_category_list( esc_html__( ', ', 'wp-bootstrap-starter' ) );
  • 831.
    		if ( $categories_list && wp_bootstrap_starter_categorized_blog() ) {
  • 832.
    			printf( '<span class="cat-links">' . esc_html__( 'Posted in %1$s', 'wp-bootstrap-starter' ) . '</span>', $categories_list ); // WPCS: XSS OK.
  • 833.
    		}
  • 834.
     
  • 835.
    		/* translators: used between list items, there is a space after the comma */
  • 836.
    		$tags_list = get_the_tag_list( '', esc_html__( ', ', 'wp-bootstrap-starter' ) );
  • 837.
    		if ( $tags_list ) {
  • 838.
    			printf( ' | <span class="tags-links">' . esc_html__( 'Tagged %1$s', 'wp-bootstrap-starter' ) . '</span>', $tags_list ); // WPCS: XSS OK.
  • 839.
    		}
  • 840.
    	}
  • 841.
     
  • 842.
     
  • 843.
    	edit_post_link(
  • 844.
    		sprintf(
  • 845.
    			/* translators: %s: Name of current post */
  • 846.
    			esc_html__( 'Edit %s', 'wp-bootstrap-starter' ),
  • 847.
    			the_title( '<span class="screen-reader-text">"', '"</span>', false )
  • 848.
    		),
  • 849.
    		' | <span class="edit-link">',
  • 850.
    		'</span>'
  • 851.
    	);
  • 852.
    }
  • 853.
    endif;
  • 854.
     
  • 855.
    // accordion menu nav walker
  • 856.
    class CSS_Menu_Maker_Walker extends Walker {
  • 857.
     
  • 858.
      var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' );
  • 859.
     
  • 860.
      function start_lvl( &$output, $depth = 0, $args = array() ) {
  • 861.
        $indent = str_repeat("\t", $depth);
  • 862.
        $output .= "\n$indent<ul>\n";
  • 863.
      }
  • 864.
     
  • 865.
      function end_lvl( &$output, $depth = 0, $args = array() ) {
  • 866.
        $indent = str_repeat("\t", $depth);
  • 867.
        $output .= "$indent</ul>\n";
  • 868.
      }
  • 869.
     
  • 870.
      function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
  • 871.
     
  • 872.
        global $wp_query;
  • 873.
        $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
  • 874.
        $class_names = $value = '';
  • 875.
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
  • 876.
     
  • 877.
        /* Add active class */
  • 878.
        if(in_array('current-menu-item', $classes)) {
  • 879.
          $classes[] = 'active';
  • 880.
          unset($classes['current-menu-item']);
  • 881.
        }
  • 882.
     
  • 883.
        /* Check for children */
  • 884.
        $children = get_posts(array('post_type' => 'nav_menu_item', 'nopaging' => true, 'numberposts' => 1, 'meta_key' => '_menu_item_menu_item_parent', 'meta_value' => $item->ID));
  • 885.
        if (!empty($children)) {
  • 886.
          $classes[] = 'has-sub';
  • 887.
        }
  • 888.
     
  • 889.
        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
  • 890.
        $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
  • 891.
     
  • 892.
        $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
  • 893.
        $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
  • 894.
     
  • 895.
        $output .= $indent . '<li' . $id . $value . $class_names .'>';
  • 896.
     
  • 897.
        $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
  • 898.
        $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
  • 899.
        $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
  • 900.
        $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
  • 901.
     
  • 902.
        $item_output = $args->before;
  • 903.
        $item_output .= '<a'. $attributes .'><span>';
  • 904.
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
  • 905.
        $item_output .= '</span></a>';
  • 906.
        $item_output .= $args->after;
  • 907.
     
  • 908.
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
  • 909.
      }
  • 910.
     
  • 911.
      function end_el( &$output, $item, $depth = 0, $args = array() ) {
  • 912.
        $output .= "</li>\n";
  • 913.
      }
  • 914.
    }
  • 915.
     
  • 916.
    ?>
  • 917.
     
<?php //flush_rewrite_rules( false ); // Limit form submissions to prevent duplicates // http://gravitywiz.com/better-limit-submission-per-time-period-by-user-or-ip/ /** * Gravity Wiz // Gravity Forms // Limit Submissions Per Time Period (by IP, User, Role, Form URL, or Field Value) * * Limit the number of times a form can be submitted per a specific time period. You modify this limit to apply to * the visitor's IP address, the user's ID, the user's role, a specific form URL, or the value of a specific field. * These "limiters" can be combined to create more complex limitations. * * @version 3.0 * @author David Smith <[email protected]> * @license GPL-2.0+ * @link http://gravitywiz.com/better-limit-submission-per-time-period-by-user-or-ip/ */ class GW_Submission_Limit { var $_args; var $_notification_event; private static $forms_with_individual_settings = array(); public function __construct( $args ) { // make sure we're running the required minimum version of Gravity Forms if( ! property_exists( 'GFCommon', 'version' ) || ! version_compare( GFCommon::$version, '1.8', '>=' ) ) return; $this->_args = wp_parse_args( $args, array( 'form_id' => false, 'form_ids' => array(), 'limit' => 1, 'limit_by' => 'ip', // 'ip', 'user_id', 'role', 'embed_url', 'field_value' 'time_period' => 60 * 60 * 24, // integer in seconds or 'day', 'month', 'year' to limit to current day, month, or year respectively 'limit_message' => __( 'Sorry, you have reached the submission limit for this form.' ), 'apply_limit_per_form' => true, 'enable_notifications' => false ) ); if( ! is_array( $this->_args['limit_by'] ) ) { $this->_args['limit_by'] = array( $this->_args['limit_by'] ); } if( empty( $this->_args['form_ids'] ) ) { if( $this->_args['form_id'] === false ) { $this->_args['form_ids'] = false; } elseif( ! is_array( $this->_args['form_id'] ) ) { $this->_args['form_ids'] = array( $this->_args['form_id'] ); } else { $this->_args['form_ids'] = $this->_args['form_id']; } } if( $this->_args['form_ids'] ) { foreach( $this->_args['form_ids'] as $form_id ) { self::$forms_with_individual_settings[] = $form_id; } } add_action( 'init', array( $this, 'init' ) ); } public function init() { add_filter( 'gform_pre_render', array( $this, 'pre_render' ) ); add_filter( 'gform_validation', array( $this, 'validate' ) ); if( $this->_args['enable_notifications'] ) { $this->enable_notifications(); add_action( 'gform_after_submission', array( $this, 'maybe_send_limit_reached_notifications' ), 10, 2 ); } } public function pre_render( $form ) { if( ! $this->is_applicable_form( $form ) || ! $this->is_limit_reached( $form['id'] ) ) { return $form; } $submission_info = rgar( GFFormDisplay::$submission, $form['id'] ); // if no submission, hide form // if submission and not valid, hide form // unless 'field_value' limiter is applied if( ( ! $submission_info || ! rgar( $submission_info, 'is_valid' ) ) && ! $this->is_limited_by_field_value() ) { add_filter( 'gform_get_form_filter_' . $form['id'], array( $this, 'get_limit_message' ), 10, 2 ); } return $form; } public function get_limit_message() { ob_start(); ?> <div class="limit-message"> <?php echo do_shortcode( $this->_args['limit_message'] ); ?> </div> <?php return ob_get_clean(); } public function validate( $validation_result ) { if( ! $this->is_applicable_form( $validation_result['form'] ) || ! $this->is_limit_reached( $validation_result['form']['id'] ) ) { return $validation_result; } $validation_result['is_valid'] = false; if( $this->is_limited_by_field_value() ) { $field_ids = array_map( 'intval', $this->get_limit_field_ids() ); foreach( $validation_result['form']['fields'] as &$field ) { if( in_array( $field['id'], $field_ids ) ) { $field['failed_validation'] = true; $field['validation_message'] = do_shortcode( $this->_args['limit_message'] ); } } } return $validation_result; } public function is_limit_reached( $form_id ) { return $this->get_entry_count( $form_id ) >= $this->get_limit(); } public function get_entry_count( $form_id ) { global $wpdb; $where = array(); $join = array(); $where[] = 'e.status = "active"'; foreach( $this->_args['limit_by'] as $limiter ) { switch( $limiter ) { case 'role': // user ID is required when limiting by role case 'user_id': $where[] = $wpdb->prepare( 'e.created_by = %s', get_current_user_id() ); break; case 'embed_url': $where[] = $wpdb->prepare( 'e.source_url = %s', GFFormsModel::get_current_page_url()); break; case 'field_value': $values = $this->get_limit_field_values( $form_id, $this->get_limit_field_ids() ); // if there is no value submitted for any of our fields, limit is never reached if( empty( $values ) ) { return false; } foreach( $values as $field_id => $value ) { $table_slug = sprintf( 'em%s', str_replace( '.', '_', $field_id ) ); $join[] = "INNER JOIN {$wpdb->prefix}gf_entry_meta {$table_slug} ON {$table_slug}.entry_id = e.id"; $where[] = $wpdb->prepare( "\n( ( {$table_slug}.meta_key BETWEEN %s AND %s ) AND {$table_slug}.meta_value = %s )", doubleval( $field_id ) - 0.001, doubleval( $field_id ) + 0.001, $value ); } break; default: $where[] = $wpdb->prepare( 'ip = %s', GFFormsModel::get_ip() ); } } if( $this->_args['apply_limit_per_form'] || ( ! $this->is_global( $form_id ) && count( $this->_args['form_ids'] ) <= 1 ) ) { $where[] = $wpdb->prepare( 'e.form_id = %d', $form_id ); } else { $where[] = $wpdb->prepare( 'e.form_id IN( %s )', implode( ', ', $this->_args['form_ids'] ) ); } $time_period = $this->_args['time_period']; $time_period_sql = false; if( $time_period === false ) { // no time period } else if( intval( $time_period ) > 0 ) { $time_period_sql = $wpdb->prepare( 'date_created BETWEEN DATE_SUB(utc_timestamp(), INTERVAL %d SECOND) AND utc_timestamp()', $this->_args['time_period'] ); } else { $gmt_offset = get_option( 'gmt_offset' ); $date_func = $gmt_offset < 0 ? 'DATE_SUB' : 'DATE_ADD'; $hour_offset = abs( $gmt_offset ); $date_created_sql = sprintf( '%s( date_created, INTERVAL %d HOUR )', $date_func, $hour_offset ); $utc_timestamp_sql = sprintf( '%s( utc_timestamp(), INTERVAL %d HOUR )', $date_func, $hour_offset ); switch( $time_period ) { case 'per_day': case 'day': $time_period_sql = "DATE( $date_created_sql ) = DATE( $utc_timestamp_sql )"; break; case 'per_week': case 'week': $time_period_sql = "WEEK( $date_created_sql ) = WEEK( $utc_timestamp_sql )"; $time_period_sql .= "AND YEAR( $date_created_sql ) = YEAR( $utc_timestamp_sql )"; break; case 'per_month': case 'month': $time_period_sql = "MONTH( $date_created_sql ) = MONTH( $utc_timestamp_sql )"; $time_period_sql .= "AND YEAR( $date_created_sql ) = YEAR( $utc_timestamp_sql )"; break; case 'per_year': case 'year': $time_period_sql = "YEAR( $date_created_sql ) = YEAR( $utc_timestamp_sql )"; break; } } if( $time_period_sql ) { $where[] = $time_period_sql; } $where = implode( ' AND ', $where ); $join = implode( "\n", $join ); $sql = "SELECT count( e.id ) FROM {$wpdb->prefix}gf_entry e $join WHERE $where"; $entry_count = $wpdb->get_var( $sql ); return $entry_count; } public function is_limited_by_field_value() { return in_array( 'field_value', $this->_args['limit_by'] ); } public function get_limit_field_ids() { $limit = $this->_args['limit']; if( is_array( $limit ) ) { $field_ids = array_keys( $this->_args['limit'] ); $field_ids = array( array_shift( $field_ids ) ); } else { $field_ids = $this->_args['fields']; } return $field_ids; } public function get_limit_field_values( $form_id, $field_ids ) { $form = GFAPI::get_form( $form_id ); $values = array(); foreach( $field_ids as $field_id ) { $field = GFFormsModel::get_field( $form, $field_id ); if( ! $field ) { continue; } $input_name = 'input_' . str_replace( '.', '_', $field_id ); $value = GFFormsModel::prepare_value( $form, $field, rgpost( $input_name ), $input_name, null ); if( ! rgblank( $value ) ) { $values[ "$field_id" ] = $value; } } return $values; } public function get_limit() { $limit = $this->_args['limit']; if( $this->is_limited_by_field_value() ) { $limit = is_array( $limit ) ? array_shift( $limit ) : intval( $limit ); } else if( in_array( 'role', $this->_args['limit_by'] ) ) { $limit = rgar( $limit, $this->get_user_role() ); } return intval( $limit ); } public function get_user_role() { $user = wp_get_current_user(); $role = reset( $user->roles ); return $role; } public function enable_notifications() { if( ! class_exists( 'GW_Notification_Event' ) ) { _doing_it_wrong( 'GW_Inventory::$enable_notifications', __( 'Inventory notifications require the \'GW_Notification_Event\' class.' ), '1.0' ); } else { $event_slug = implode( array_filter( array( "gw_submission_limit_limit_reached", $this->_args['form_id'] ) ) ); $event_name = GFForms::get_page() == 'notification_edit' ? __( 'Submission limit reached' ) : __( 'Event name is only populated on Notification Edit view; saves a DB call to get the form on every ' ); $this->_notification_event = new GW_Notification_Event( array( 'form_id' => $this->_args['form_id'], 'event_name' => $event_name, 'event_slug' => $event_slug //'trigger' => array( $this, 'notification_event_listener' ) ) ); } } public function maybe_send_limit_reached_notifications( $entry, $form ) { if( $this->is_applicable_form( $form ) && $this->is_limit_reached( $form['id'] ) ) { $this->send_limit_reached_notifications( $form, $entry ); } } public function send_limit_reached_notifications( $form, $entry ) { $this->_notification_event->send_notifications( $this->_notification_event->get_event_slug(), $form, $entry, true ); } public function is_applicable_form( $form ) { $form_id = isset( $form['id'] ) ? $form['id'] : $form; $is_specific_form = ! $this->is_global( $form_id ) ? in_array( $form_id, $this->_args['form_ids'] ) : false; return $this->is_global( $form_id ) || $is_specific_form; } public function is_global( $form) { $form_id = isset( $form['id'] ) ? $form['id'] : $form; return empty( $this->_args['form_ids'] ) && ! in_array( $form_id, self::$forms_with_individual_settings ); } } class GWSubmissionLimit extends GW_Submission_Limit { } new GW_Submission_Limit( array( 'form_id' => 4, 'limit_by' => 'field_value', 'limit' => array( // "2" is your field ID, "6" is your limit for this field ID 5 => 1 ), 'time_period' => false // forever! ) ); //Remove Gutenberg Block Library CSS from loading on the frontend function smartwp_remove_wp_block_library_css(){ wp_dequeue_style( 'wp-block-library' ); wp_dequeue_style( 'wp-block-library-theme' ); } add_action( 'wp_enqueue_scripts', 'smartwp_remove_wp_block_library_css' ); // Change default excerpt ellipses function new_excerpt_more($more) { return '...'; } add_filter('excerpt_more', 'new_excerpt_more'); function themeprefix_show_cpt_archives( $query ) { if( is_category() || is_tag() && empty( $query->query_vars['suppress_filters'] ) ) { $query->set( 'post_type', array( 'nav_menu_item', 'oped', 'video', 'recent-case', 'feat-press', 'post' )); return $query; } } add_filter( 'pre_get_posts', 'themeprefix_show_cpt_archives' ); // Remove the word archive from archive page titles //https://www.binarymoon.co.uk/2017/02/hide-archive-title-prefix-wordpress/ function hap_hide_the_archive_title( $title ) { // Skip if the site isn't LTR, this is visual, not functional. // Should try to work out an elegant solution that works for both directions. if ( is_rtl() ) { return $title; } // Split the title into parts so we can wrap them with spans. $title_parts = explode( ': ', $title, 2 ); // Glue it back together again. if ( ! empty( $title_parts[1] ) ) { $title = wp_kses( $title_parts[1], array( 'span' => array( 'class' => array(), ), ) ); $title = '<span class="screen-reader-text">' . esc_html( $title_parts[0] ) . ': </span>' . $title; } return $title; } add_filter( 'get_the_archive_title', 'hap_hide_the_archive_title' ); function video_posttype() { register_post_type( 'video', // CPT Options array( 'labels' => array( 'name' => __( 'Videos' ), 'singular_name' => __( 'Video' ) ), // Features this CPT supports in Post Editor 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',), 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'video'), 'taxonomies' => array('category', 'post_tag'), ) ); } // Hooking up our function to theme setup add_action( 'init', 'video_posttype' ); function oped_posttype() { register_post_type( 'oped', // CPT Options array( 'labels' => array( 'name' => __( 'Op - Eds' ), 'singular_name' => __( 'Op - Ed' ) ), // Features this CPT supports in Post Editor 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',), 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'oped'), 'taxonomies' => array('category'), ) ); } // Hooking up our function to theme setup add_action( 'init', 'oped_posttype' ); function verdict_posttype() { register_post_type( 'verdict', // CPT Options array( 'labels' => array( 'name' => __( 'Verdicts' ), 'singular_name' => __( 'Verdict' ) ), // Features this CPT supports in Post Editor 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',), 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'verdict'), 'taxonomies' => array('category'), ) ); } // Hooking up our function to theme setup add_action( 'init', 'verdict_posttype' ); function featPress_posttype() { register_post_type( 'feat-press', // CPT Options array( 'labels' => array( 'name' => __( 'Press Coverage' ), 'singular_name' => __( 'Press Coverage' ) ), // Features this CPT supports in Post Editor 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields', 'excerpt',), 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'feat-press'), 'taxonomies' => array('category'), ) ); } // Hooking up our function to theme setup add_action( 'init', 'featPress_posttype' ); function recentCase_posttype() { register_post_type( 'recent-case', // CPT Options array( 'labels' => array( 'name' => __( 'Recent Cases' ), 'singular_name' => __( 'Recent Case' ) ), // Features this CPT supports in Post Editor 'supports' => array( 'title', 'editor', 'thumbnail', 'revisions', 'custom-fields',), 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'recent-case'), 'taxonomies' => array('category'), ) ); } // Hooking up our function to theme setup add_action( 'init', 'recentCase_posttype' ); /* function create_posttype() { register_post_type( 'bio', // CPT Options array( 'labels' => array( 'name' => __( 'Team Bios' ), 'singular_name' => __( 'Bio' ) ), // Features this CPT supports in Post Editor 'supports' => array( 'title', 'editor', 'page-attributes', 'thumbnail', 'revisions', 'custom-fields', ), 'public' => true, 'has_archive' => true, 'rewrite' => array('slug' => 'bio'), 'taxonomies' => array('alpha'), ) ); } // Hooking up our function to theme setup add_action( 'init', 'create_posttype' );*/ /* Sort team members like page order i.e. the number assigned */ function team_custom_post_order_sort( $query ){ if ( $query->is_main_query() && is_post_type_archive( 'bio' )){ $query->set( 'orderby', 'menu_order' ); $query->set( 'order' , 'ASC' ); } } add_action( 'pre_get_posts' , 'team_custom_post_order_sort' ); // Remove pagination on team bio archive page function no_nopaging_leadership_index($query) { if (is_post_type_archive('bio') && is_main_query()) { $query->set('nopaging', 1); } } add_action('parse_query', 'no_nopaging_leadership_index'); // Custom alpha taxonomy function alphaindex_alpha_tax() { register_taxonomy( 'alpha',array ( 0 => 'bio', ), array( 'hierarchical' => false, 'label' => 'Alpha', 'show_ui' => false, 'query_var' => true, 'show_admin_column' => false, ) ); } add_action('init', 'alphaindex_alpha_tax'); // Automatically assign the right alpha taxonomy to bio posts on save function alphaindex_save_alpha( $post_id ) { if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return; //only run for bio $slug = 'bio'; $letter = ''; // If this isn't a 'song' post, don't update it. if ( isset( $_POST['post_type'] ) && ( $slug != $_POST['post_type'] ) ) return; // Check permissions if ( !current_user_can( 'edit_post', $post_id ) ) return; // OK, we're authenticated: we need to find and save the data $taxonomy = 'alpha'; if ( isset( $_POST['post_type'] ) ) { // Get the title of the post // $title = strtolower( $_POST['post_title'] ); // Get the last word in a title https://stackoverflow.com/questions/18612872/get-the-last-word-of-a-string $string = strtolower( $_POST['post_title'] ); $last_word_start = strrpos($string, ' ') + 1; // +1 so we don't include the space in our result $last_word = substr($string, $last_word_start); // $last_word = PHP. // The next few lines remove A, An, or The from the start of the title /*$splitTitle = explode(" ", $title); $blacklist = array("an","a","the"); $splitTitle[0] = str_replace($blacklist,"",strtolower($splitTitle[0])); $title = implode("", $splitTitle);*/ // Get the first letter of the title //$letter = substr( $title, 0, 1 ); $letter = substr( $last_word, 0, 1 ); // Set to 0-9 if it's a number if ( is_numeric( $letter ) ) { $letter = '0-9'; } } //set term as first letter of post title, lower case wp_set_post_terms( $post_id, $letter, $taxonomy ); } add_action( 'save_post', 'alphaindex_save_alpha' ); // Enque Google Fonts function bg_load_google_fonts() { wp_enqueue_style( 'google-fonts', '//fonts.googleapis.com/css?family=DM+Serif+Display:400', array(), '1' ); } add_action( 'wp_enqueue_scripts', 'bg_load_google_fonts' ); // Allows you to reference all blog type pages with is_blog() with conditional statements // https://wordpress.stackexchange.com/questions/107141/check-if-current-page-is-the-blog-page function is_blog () { return ( is_archive() || is_author() || is_category() || is_home() || is_single() || is_tag()) && 'post' == get_post_type(); } // Prevents any user from accessing the Appearance > Customize menu add_filter('map_meta_cap', function($caps, $cap, $user_id, $args) { if ('customize' == $cap) return ['do_not_allow']; return $caps; }, 10, 4); function remove_unnecessary_wordpress_menus(){ global $submenu; unset($submenu['themes.php'][11]); unset($submenu['themes.php'][12]); } add_action('admin_menu', 'remove_unnecessary_wordpress_menus', 999); /** * WCAG 2.0 Attributes for Dropdown Menus * * Adjustments to menu attributes tot support WCAG 2.0 recommendations * for flyout and dropdown menus. * * @ref https://www.w3.org/WAI/tutorials/menus/flyout/ */ function wcag_nav_menu_link_attributes( $atts, $item, $args, $depth ) { // Add [aria-haspopup] and [aria-expanded] to menu items that have children $item_has_children = in_array( 'menu-item-has-children', $item->classes ); if ( $item_has_children ) { $atts['aria-haspopup'] = "true"; $atts['aria-expanded'] = "false"; } return $atts; } add_filter( 'nav_menu_link_attributes', 'wcag_nav_menu_link_attributes', 10, 4 ); // Update Jquery to latest version function replace_core_jquery_version() { // Deregister WP core jQuery wp_deregister_script( 'jquery' ); // the jquery handle is just an alias to load jquery-core with jquery-migrate // Deregister WP jQuery wp_deregister_script( 'jquery-core' ); // Deregister WP jQuery Migrate wp_deregister_script( 'jquery-migrate' ); // Re-add latest jquery ver wp_register_script( 'jquery', "//code.jquery.com/jquery-3.4.1.min.js", array(), '3.3.1' ); wp_enqueue_script('jquery'); // Re-add jquery migrate - only need if support for jquery ver older than 1.9 is needed // wp_register_script( 'jquery-migrate', "https://code.jquery.com/jquery-migrate-3.1.0.min.js", array(), '3.1.0' ); // wp_enqueue_script('jquery-migrate'); } add_action( 'wp_enqueue_scripts', 'replace_core_jquery_version' ); // Disables tabindex on Gravity Forms add_filter( 'gform_tabindex', '__return_false' ); // Changes input type=submit into a button for gravity forms and disables the button on submit add_filter( 'gform_next_button', 'input_to_button', 10, 2 ); add_filter( 'gform_previous_button', 'input_to_button', 10, 2 ); add_filter( 'gform_submit_button', 'form_submit_button', 10, 2 ); function form_submit_button( $button, $form ) { return "<button class='btn btn--form d-block' id='gform_submit_button_{$form['id']}' onclick='var e=this;setTimeout(function(){e.disabled=true;},0);return true;'>Send Your Information</button>"; } // Adds category class to body tag add_filter('body_class','add_category_to_single'); function add_category_to_single($classes) { if (is_single() ) { global $post; foreach((get_the_category($post->ID)) as $category) { // add category slug to the $classes array $classes[] = $category->category_nicename; } } // return the $classes array return $classes; } //Excludes "News & Media" category from blog page function exclude_category($query) { if ( $query->is_home() ) { $query->set('cat', '-3'); } return $query; } add_filter('pre_get_posts', 'exclude_category'); // Gravity forms scroll to form on validation add_filter( 'gform_confirmation_anchor', '__return_true' ); // Dequeue fontawesome free function dequeue_fontawesome_free() { wp_dequeue_style( 'wp-bootstrap-starter-fontawesome-cdn' ); wp_deregister_style( 'wp-bootstrap-starter-fontawesome-cdn' ); } add_action( 'wp_print_styles', 'dequeue_fontawesome_free' ); // Dequeue boostrap function dequeue_boostrap() { wp_dequeue_style( 'wp-bootstrap-starter-bootstrap-css' ); wp_deregister_style( 'wp-bootstrap-starter-bootstrap-css' ); } add_action( 'wp_print_styles', 'dequeue_boostrap' ); // Register + re-enque fontawesome pro function load_fontawesome_kit() { wp_register_script( 'font-awesome-pro', "https://kit.fontawesome.com/997b2a3cbf.js", array(), '5.10.2' ); wp_enqueue_script('font-awesome-pro'); } add_action( 'get_footer', 'load_fontawesome_kit', 0 ); // Enque child theme styles function zblocks_enqueue_style() { wp_enqueue_style( 'child-style', get_stylesheet_directory_uri() . '/css/style.css' ); } add_action( 'wp_enqueue_scripts', 'zblocks_enqueue_style', 1 ); // Additional menu function register_my_menu() { register_nav_menu('dupe-menu',__( 'Secondary Menu' )); } add_action( 'init', 'register_my_menu' ); // ACF Options Page if( function_exists('acf_add_options_page') ) { //acf_add_options_page(); acf_add_options_page(array( 'page_title' => 'Theme General Settings', 'menu_title' => 'Admin Settings', 'menu_slug' => 'theme-general-settings', 'capability' => 'manage_options', 'redirect' => true, )); acf_add_options_sub_page(array( 'page_title' => 'Firm Information', 'menu_title' => 'Firm Info', 'parent_slug' => 'theme-general-settings' )); acf_add_options_sub_page(array( 'page_title' => 'Theme Header Settings', 'menu_title' => 'Header', 'parent_slug' => 'theme-general-settings', )); acf_add_options_sub_page(array( 'page_title' => 'Home Page Layout', 'menu_title' => 'Home Page Layout', 'parent_slug' => 'theme-general-settings', )); acf_add_options_sub_page(array( 'page_title' => 'Theme Footer Settings', 'menu_title' => 'Footer', 'parent_slug' => 'theme-general-settings', )); } // force scss to be processed on page load define('WP_SCSS_ALWAYS_RECOMPILE', true); //override parent theme posted_on if ( ! function_exists( 'wp_bootstrap_starter_posted_on' ) ) : /** * Prints HTML with meta information for the current post-date/time and author. */ function wp_bootstrap_starter_posted_on() { $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>'; if ( get_the_time( 'U' ) !== get_the_modified_time( 'U' ) ) { $time_string = '<time class="entry-date published" datetime="%1$s">%2$s</time>'; } $time_string = sprintf( $time_string, esc_attr( get_the_date( 'c' ) ), esc_html( get_the_date() ) ); $posted_on = sprintf( esc_html_x( 'Posted on %s', 'post date', 'wp-bootstrap-starter' ), '<a href="' . esc_url( get_permalink() ) . '" rel="bookmark">' . $time_string . '</a>' ); $byline = sprintf( esc_html_x( 'by %s', 'post author', 'wp-bootstrap-starter' ), '<span class="author vcard"><a class="url fn n" href="' . esc_url( get_author_posts_url( get_the_author_meta( 'ID' ) ) ) . '">' . esc_html( get_the_author() ) . '</a></span>' ); echo '<span class="posted-on">' . $posted_on . '</span>'; // WPCS: XSS OK. } endif; if ( ! function_exists( 'wp_bootstrap_starter_entry_footer' ) ) : /** * Prints HTML with meta information for the categories, tags and comments. */ function wp_bootstrap_starter_entry_footer() { // Hide category and tag text for pages. if ( 'post' === get_post_type() ) { /* translators: used between list items, there is a space after the comma */ $categories_list = get_the_category_list( esc_html__( ', ', 'wp-bootstrap-starter' ) ); if ( $categories_list && wp_bootstrap_starter_categorized_blog() ) { printf( '<span class="cat-links">' . esc_html__( 'Posted in %1$s', 'wp-bootstrap-starter' ) . '</span>', $categories_list ); // WPCS: XSS OK. } /* translators: used between list items, there is a space after the comma */ $tags_list = get_the_tag_list( '', esc_html__( ', ', 'wp-bootstrap-starter' ) ); if ( $tags_list ) { printf( ' | <span class="tags-links">' . esc_html__( 'Tagged %1$s', 'wp-bootstrap-starter' ) . '</span>', $tags_list ); // WPCS: XSS OK. } } edit_post_link( sprintf( /* translators: %s: Name of current post */ esc_html__( 'Edit %s', 'wp-bootstrap-starter' ), the_title( '<span class="screen-reader-text">"', '"</span>', false ) ), ' | <span class="edit-link">', '</span>' ); } endif; // accordion menu nav walker class CSS_Menu_Maker_Walker extends Walker { var $db_fields = array( 'parent' => 'menu_item_parent', 'id' => 'db_id' ); function start_lvl( &$output, $depth = 0, $args = array() ) { $indent = str_repeat("\t", $depth); $output .= "\n$indent<ul>\n"; } function end_lvl( &$output, $depth = 0, $args = array() ) { $indent = str_repeat("\t", $depth); $output .= "$indent</ul>\n"; } function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) { global $wp_query; $indent = ( $depth ) ? str_repeat( "\t", $depth ) : ''; $class_names = $value = ''; $classes = empty( $item->classes ) ? array() : (array) $item->classes; /* Add active class */ if(in_array('current-menu-item', $classes)) { $classes[] = 'active'; unset($classes['current-menu-item']); } /* Check for children */ $children = get_posts(array('post_type' => 'nav_menu_item', 'nopaging' => true, 'numberposts' => 1, 'meta_key' => '_menu_item_menu_item_parent', 'meta_value' => $item->ID)); if (!empty($children)) { $classes[] = 'has-sub'; } $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) ); $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : ''; $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args ); $id = $id ? ' id="' . esc_attr( $id ) . '"' : ''; $output .= $indent . '<li' . $id . $value . $class_names .'>'; $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr( $item->attr_title ) .'"' : ''; $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr( $item->target ) .'"' : ''; $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr( $item->xfn ) .'"' : ''; $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr( $item->url ) .'"' : ''; $item_output = $args->before; $item_output .= '<a'. $attributes .'><span>'; $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; $item_output .= '</span></a>'; $item_output .= $args->after; $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } function end_el( &$output, $item, $depth = 0, $args = array() ) { $output .= "</li>\n"; } } ?>

Copy Code to Clipboard Raw

Sign-in or Create a Free Account.

Snippi uses Twitter or Facebook to register and create accounts. Registration will enable you to keep track of your snippets. We never spam your timeline or wall. Ever.

Sign-in with Facebook Sign-in with Twitter